Onsite Script Integration

The onsite script is the main integration point for Ezoic Subscriptions. It gives your site access to subscriber access checks, Ezoic's pre-built paywall and checkout experience, donation dialogs, and passwordless subscriber login.

Add the Script 🔗

Add the Ezoic Subscriptions script on pages where subscriptions or donations should work:

<script src="https://sm.ezoic.com/min.js" async defer></script>

Because the script loads asynchronously, wrap your integration code in the ezsubscriptions.cmd queue. The callback runs after the widget is ready.

Publisher-Managed Paid Access 🔗

Replace premium-access with the access key your site checks, and premium-plan with the offer key you want checkout to sell. Both come from your Ezoic offer.

<div class="paywalled-content" data-premium-content hidden>
  <!-- Subscriber-only content goes here. -->
</div>

<script>
  window.ezsubscriptions = window.ezsubscriptions || {};
  ezsubscriptions.cmd = ezsubscriptions.cmd || [];
  ezsubscriptions.cmd.push(async function () {
    const access = await ezsubscriptions.hasAccess("premium-access");
    if (access.decision === "allowed") {
      document.querySelector("[data-premium-content]").hidden = false;
      return;
    }

    ezsubscriptions.showPaywall({ offer: "premium-plan" });
  });
</script>
<script src="https://sm.ezoic.com/min.js" async defer></script>

hasAccess takes the access key; showPaywall({ offer }) takes the offer key. They are different identifiers from the same offer.

What showPaywall({ offer }) Does 🔗

ezsubscriptions.showPaywall({ offer: "premium-plan" }) opens Ezoic's pre-built paywall and checkout experience for the products in the premium-plan offer.

The widget:

  • Loads the sellable products for the offer.
  • Re-checks whether the current visitor already has access.
  • Shows the paywall and checkout experience when the visitor does not have access.
  • Renders nothing if the visitor already holds an access key the offer grants.
  • Renders nothing if the offer key is unknown, inactive, or has no active products.

The offer value is the offer key from your Ezoic dashboard, not the access key and not the public display name.

For the full showPaywall() options, callback hooks, and return values, see JavaScript API Reference.

Protecting Full Content 🔗

The widget decides whether a visitor has access and provides the paywall and checkout experience. Your site still controls what content is sent to the browser and when full content is revealed.

For casual paid access, a soft gate may be enough: include the full content in the HTML and hide it until hasAccess(...) returns allowed.

For stronger protection, use a hybrid approach:

  1. Show the headline and teaser to everyone.
  2. Check access with ezsubscriptions.hasAccess(...).
  3. Fetch or render the full body only after access is allowed.

Do not rely on a visual overlay alone if the full article is already visible in the page source and you need stronger content protection.

SEO Markup Is Required For Gated Articles 🔗

Gated article pages should include paywalled-content structured data so search engines understand that subscriber-only content is intentionally paywalled. Follow SEO and Paywalling Best Practices before going live.

Stripe Content Security Policy 🔗

If your site uses a strict Content Security Policy, allow Stripe so checkout can load. Stripe's current guidance can change, so use Stripe's official CSP documentation as the source of truth: Content Security Policy.

Common allowlist entries include:

  • script-src https://js.stripe.com https://*.js.stripe.com
  • frame-src https://js.stripe.com https://*.js.stripe.com https://hooks.stripe.com
  • connect-src https://api.stripe.com https://*.stripe.com
  • img-src https://*.stripe.com

Dashboard Prerequisites 🔗

Before checkout can sell access, the site needs an active payment setup and a publisher-managed offer with an access key and an offer key. See Payment Setup and Offers, Tiers, and Paid Access for those setup details.