JavaScript API Reference

The onsite script exposes window.ezsubscriptions after https://sm.ezoic.com/min.js loads. Because the script loads asynchronously, put API calls inside the cmd queue:

<script>
  window.ezsubscriptions = window.ezsubscriptions || {};
  ezsubscriptions.cmd = ezsubscriptions.cmd || [];
  ezsubscriptions.cmd.push(function (api) {
    // api is the resolved ezsubscriptions API.
  });
</script>
<script src="https://sm.ezoic.com/min.js" async defer></script>

Methods that return promises can reject if a network request fails. Wrap access checks and checkout-launching calls in try / catch when your page needs a custom fallback.

Readiness 🔗

ezsubscriptions.cmd 🔗

Queues callbacks until the script is ready. Each callback receives the resolved API object.

ezsubscriptions.cmd.push(function (api) {
  api.showPaywall({ offer: "premium-plan" });
});

Callbacks pushed after the script is ready run immediately.

ezsubscriptions.ready 🔗

Boolean value that is true after the API is ready.

if (window.ezsubscriptions?.ready) {
  window.ezsubscriptions.showPaywall({ offer: "premium-plan" });
}

Access Methods 🔗

hasAccess(query) 🔗

Checks whether the current visitor has an active entitlement for an access key.

const access = await ezsubscriptions.hasAccess("premium-access");

You can pass the access key directly or as an object:

await ezsubscriptions.hasAccess("premium-access");
await ezsubscriptions.hasAccess({ tier: "premium-access" });

Parameters:

  • query: string | { tier: string } — access key from your publisher-managed offer.

Returns:

{
  decision: "allowed" | "denied" | "login_required" | "expired" | "revoked" | "unknown_product",
  reasonCode: string
}

Show protected content only when decision is allowed. Treat every other decision as no current access.

Anonymous visitors return login_required without a network request.

This promise can reject if the visitor is signed in and the access request fails.

getAccessTiers() 🔗

Returns the access keys currently held by the visitor.

const tiers = await ezsubscriptions.getAccessTiers();
if (tiers.includes("pro")) {
  enableProFeatures();
}

Parameters: none.

Returns:

string[]

Anonymous visitors return [] without a network request.

This promise can reject if the visitor is signed in and the access-tier request fails.

Paywall Methods 🔗

showPaywall(options) 🔗

Opens Ezoic's pre-built paywall and checkout experience.

For publisher-managed offers, pass the offer key with offer:

await ezsubscriptions.showPaywall({
  offer: "premium-plan",
  onSuccess: function (result) {
    window.location.reload();
  },
  onError: function (error) {
    console.log(error.message);
  },
});

Parameters:

  • options?: object
  • options.offer?: string — offer key from your publisher-managed offer. This is the normal option for publisher-managed access. It is the offer key, not the access key you pass to hasAccess.
  • options.dismissible?: boolean — when true, the visitor can close the paywall and onCancel can fire. When omitted or false, the paywall is blocking.
  • options.onSuccess?: (result: CheckoutResult) => void — fires after checkout completes and access is established.
  • options.onCancel?: () => void — fires when a dismissible paywall is closed before checkout completes.
  • options.onError?: (error: CheckoutError) => void — fires when a checkout attempt fails. It may fire more than once if the visitor retries.
  • options.config?: PageConfig — advanced support-directed option. Most publisher-managed integrations should omit this.
  • options.path?: string — advanced support-directed option. Not needed for offer-key checkout.

Returns:

Promise<void>

When offer is provided, the widget loads that offer's products, re-checks visitor access, and renders nothing if the visitor already holds an access key the offer grants or if there are no active products to sell.

hide() 🔗

Unmounts the paywall and donation surfaces.

ezsubscriptions.hide();

Parameters: none.

Returns: void.

Donation Methods 🔗

showDonations(options) 🔗

Mounts the donation launcher and registers openDonation() / closeDonation().

await ezsubscriptions.showDonations({
  onSuccess: function (result) {
    console.log("Donation complete", result.amountCents);
  },
});

Parameters:

  • options?: object
  • options.onSuccess?: (result: CheckoutResult) => void — fires after donation checkout completes.
  • options.onCancel?: () => void — fires when the visitor closes the donation dialog before checkout completes.
  • options.onError?: (error: CheckoutError) => void — fires when a checkout attempt fails. It may fire more than once if the visitor retries.
  • options.config?: PageConfig — advanced support-directed option. Most publisher-managed donation integrations should omit this.

Returns:

Promise<void>

Call showDonations() before calling openDonation().

openDonation(options) 🔗

Opens the donation dialog after showDonations() has mounted the donation launcher.

ezsubscriptions.openDonation({ amountCents: 2500 });

Parameters:

  • options?: object
  • options.amountCents?: number — preselected donation amount in cents. For example, 2500 means $25.00. The configured minimum still applies.
  • options.productId?: string — optional donation product ID. Most publisher-managed donation integrations should omit this because a site has one active donation in the current dashboard flow.

Returns: void.

If amountCents is missing, invalid, or below the configured minimum, the widget falls back to the normal donation picker.

closeDonation() 🔗

Closes the donation dialog.

ezsubscriptions.closeDonation();

Parameters: none.

Returns: void.

Callback Payloads 🔗

CheckoutResult 🔗

Passed to onSuccess.

{
  productExternalId: string,
  priceExternalId: string,
  productType: "subscription" | "one_time" | "donation",
  amountCents: number,
  offer?: string
}
  • amountCents is the requested base amount in cents. Taxes, discounts, or payment-provider adjustments can change the final charged total.
  • offer is set to the offer key when checkout was opened with showPaywall({ offer }).
  • A callback that throws is logged and does not break the widget.

CheckoutError 🔗

Passed to onError.

{
  message: string
}

Checkout stays open for retry after an error, so onError can fire more than once.