# Visitor Authentication

Source: https://docs.ezoic.com/docs/subscriptions/visitor-authentication/


Visitor authentication determines how a visitor proves who they are before Ezoic Subscriptions grants access or starts checkout. There are two modes:

- **Ezoic visitor accounts** — the default. Ezoic provides sign-in, account creation, and recovery. No integration code.
- **Bring your own login** — connect your existing login system to the widget through an `AuthAdapter`.

You select the mode in your Ezoic dashboard. The default is Ezoic visitor accounts.

## How Sign-In Works

In both modes the widget resolves a visitor identity (an email address) and uses it for access checks (`hasAccess`) and checkout. What differs is who handles sign-in and account creation:

- **Ezoic visitor accounts** — Ezoic's built-in login and create-account screens, shown in the widget.
- **Bring your own login** — your own login and sign-up pages, reached through the callbacks you register during widget setup.

At checkout, a signed-in visitor goes straight to payment. An anonymous visitor sees an identity gate offering **Log in**, **Create account**, and — when guest checkout is enabled — **Continue as a guest**. Where **Log in** and **Create account** send the visitor depends on the active mode: in Ezoic visitor accounts mode they open Ezoic's built-in login and create-account screens inside the widget; in bring-your-own-login mode they call the callbacks you supply, sending the visitor to your own login and sign-up pages.

Returning visitors sign in the same way, through the active mode's provider. As a final fallback — so a paying visitor is never left without access, for example when they return on a new device — Ezoic Subscriptions can email a one-time, passwordless access link. This is a safety net, not the primary way to sign in.

Subscribers manage their billing in the subscriber portal at `https://subscriber.ezoic.com`.

## Ezoic Visitor Accounts

This is the default mode and requires **no integration code**. Ezoic provides login, account creation, guest checkout (when you enable it), and passwordless recovery directly in the widget. You do not build or maintain any authentication on your site.

The widget places the Ezoic Accounts integration on the page for you. If your site already runs the Ezoic Accounts integration (`window.ezAuth`), leave it in place: the widget detects and reuses an existing instance and otherwise loads it itself. Either way works seamlessly, so there is nothing to add or remove.

## Bring Your Own Login

Use this mode when your site already has its own login system. You connect it to the widget by registering an `AuthAdapter` — a small object that lets the widget read the signed-in visitor's email and send visitors to your login and sign-up pages.

### The `AuthAdapter` Contract

For the related SDK methods and their full signatures — `initialize`, `authChanged`, and the rest of the surface — see the [JavaScript API Reference](/docs/subscriptions/api-reference/).

```typescript
interface AuthAdapter {
  getUserEmail: () => string | null | Promise<string | null>;
  goToLogin: () => void | Promise<void>;
  goToCreateAccount: () => void | Promise<void>;
}
```

#### `getUserEmail()`

Returns the signed-in visitor's email address, or `null` when no one is signed in. May be synchronous or return a promise.

Returns:

```typescript
string | null | Promise<string | null>
```

The widget calls this to detect a logged-in visitor and skip the checkout identity gate. Return a syntactically valid email when the visitor is authenticated in your system; return `null` (or an empty/invalid value) when the visitor is anonymous.

#### `goToLogin()`

Sends the visitor to your login experience. The adapter decides how — a navigation, a modal, or a provider SDK call.

Returns:

```typescript
void | Promise<void>
```

Powers the gate's **Log in** action and the paywall's "Already subscribed? Log in" link.

#### `goToCreateAccount()`

Sends the visitor to your account creation experience. The adapter decides how, exactly like `goToLogin`.

Returns:

```typescript
void | Promise<void>
```

Powers the gate's **Create account** action. It can point at the same destination as `goToLogin` when your login page also registers new accounts.

### Register the Adapter

Register the adapter with `ezsubscriptions.initialize({ auth })` inside the `cmd` queue, so it is set as soon as the script is ready:

```html
<script>
  window.ezsubscriptions = window.ezsubscriptions || {};
  ezsubscriptions.cmd = ezsubscriptions.cmd || [];
  ezsubscriptions.cmd.push(function (api) {
    api.initialize({
      auth: {
        getUserEmail: function () {
          // Return the signed-in visitor's email from your own auth, or null.
          return myAuth.getCurrentUser()?.email ?? null;
        },
        goToLogin: function () {
          window.location.href = "/login?return=" + encodeURIComponent(location.href);
        },
        goToCreateAccount: function () {
          window.location.href = "/signup?return=" + encodeURIComponent(location.href);
        },
      },
    });
  });
</script>
<script src="https://sm.ezoic.com/min.js" async defer></script>
```

Registration is idempotent: calling `initialize` again with a valid adapter replaces the previous one.


**Return visitors to where they left off.** When `goToLogin()` or `goToCreateAccount()` navigates a visitor away to your pages, send them back to the same URL once they sign in or create their account (the examples above pass a `return` parameter for exactly this). Call `ezsubscriptions.authChanged()` after they authenticate and the widget seamlessly resumes the checkout they had started — no extra wiring on your side.


### Signal Authentication Changes

Call `ezsubscriptions.authChanged()` whenever the visitor's login state changes — after a login, a logout, or an asynchronous session restore — so the widget re-resolves identity, refreshes the access session, and resumes any pending checkout:

```javascript
async function onLogin() {
  await myAuth.signIn(/* ... */);
  await ezsubscriptions.authChanged();
}

async function onLogout() {
  await myAuth.signOut();
  await ezsubscriptions.authChanged();
}
```

### How Checkout Uses the Adapter

- A signed-in visitor (`getUserEmail()` returns an email) skips the identity gate and goes straight to payment.
- An anonymous visitor sees **Log in**, **Create account**, and — when guest checkout is enabled — **Continue as guest**. `goToLogin()` and `goToCreateAccount()` navigate the visitor away to your pages; when they return authenticated and you call `authChanged()`, the widget resumes the same checkout.
- The email returned by `getUserEmail()` is the visitor's identity for access checks and checkout.


**Register the adapter before going live.** On a domain set to bring your own login, the widget cannot resolve a visitor's identity until `ezsubscriptions.initialize({ auth })` has registered a complete adapter with all three methods. Until then, checkout logs an error and does not complete. Configure and test your adapter before switching the domain to this mode.



**Looking for a server-to-server integration?** [Contact the Ezoic support team](https://support.ezoic.com/) and we'll send you the setup details.


## Guest Checkout

Guest checkout lets a visitor buy with just an email address instead of signing in or creating an account. At the identity gate the visitor chooses **Continue as guest**, enters an email, and pays. Access attaches to that email, so the visitor can sign in or recover access later using the same address.

Because access is tied to the email, no manual reconciliation is ever needed. If a guest later registers on your site (or already has an account) using that same email, their account — on your own login system or Ezoic visitor accounts, whichever mode you use — is linked to the purchase automatically, with no extra work for you or the visitor.

Guest checkout is a per-domain setting in your Ezoic dashboard and applies to both authentication modes.

## Next Steps

- Install the widget with [Onsite Script Integration](/docs/subscriptions/site-integration/).
- Gate content with the [Publisher-Managed Access API](/docs/subscriptions/publisher-managed-access/).
- Review method options in the [JavaScript API Reference](/docs/subscriptions/api-reference/).

