# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
This site has an agentic ask interface you may use to query the documentation dynamically by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.agego.com/index.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

---

# Overview

Everything you need to integrate AgeGO, understand how age verification works, and manage your configuration, all in one place.&#x20;

{% hint style="warning" %}
This documentation is intended exclusively for businesses, developers, and partners integrating the AgeGO solution into their websites or platforms.

If you are verifying your age on a website, visit our [Help Center](https://help.agego.com/). For questions about your personal data, including access or deletion requests, see our [Privacy Policy](https://www.agego.com/privacy-policy).
{% endhint %}

AgeGO is a secure and reliable age-verification solution designed to help businesses comply with age-restriction regulations while protecting underage users from accessing restricted content. It enables publishers and service providers to verify user age effectively, while maintaining privacy, security, and a smooth user experience.

Age verification is now a regulatory requirement in many regions. Failure to comply can result in penalties, service restrictions, or reputational risk.

AgeGO helps you meet these requirements by:

* Enforcing compliance with applicable age-verification laws.
* Preventing underage access to restricted content.
* Minimizing friction for legitimate users.
* Handling sensitive data securely and responsibly.

## <mark style="color:$primary;">Getting started</mark>

1. **Create your Business Account.** Sign up and verify your email. Your account must be approved before you can create sites. → [Sign up with AgeGO](/general/sign-up-with-agego)
2. **Create a Site.** Add your site's name, Website URL and Callback URL in the Dashboard. Each Site gets a unique `asi`. → [My Sites](/admin-panel/my-sites)
3. **Integrate AgeGO.** Choose between the Modal (Overlay) and S2S integration. → [Integration](/integration/integration)

Whether you are a developer, product manager, or compliance lead, these docs will guide you through setting up a secure and compliant age-verification flow in just a few steps.


# Sign up with AgeGO

This section explains how businesses and service providers can create an AgeGO account to integrate AgeGO as an age-verification solution on their websites or platforms.

It covers the steps required to sign up, configure your account, and access AgeGO’s verification and integration features.

## <mark style="color:$primary;">AgeGO Business Account</mark>

An AgeGO Business Account is required to implement AgeGO on your site. This section walks you through:

* The business signup process
* Email verification
* Account approval and access levels
* Next steps after registration
* Common troubleshooting during account setup

If you are looking to use AgeGO as an end user to verify your age, this section does not apply.

### <mark style="color:$info;">Create Your AgeGO Account</mark>

To get started with AgeGO, you’ll need to create a business account.

You can sign up at:

<https://dashboard.agego.com/signup>

The process takes less than a minute to complete.

Once registered, you can log in at any time using the same link.

{% hint style="warning" %}
After verifying your email, your account will require approval before you can create sites and fully use AgeGO.
{% endhint %}

### <mark style="color:$info;">Verify Your Email</mark>

After creating your account, you’ll receive a confirmation email. Click the verification link to activate your Dashboard access.

Once your email is verified:

* Your Account Status changes from **Email Not Verified** to **Not Verified**
* You can log in to the Dashboard
* Site creation remains disabled until admin approval

If you don’t see the email:

1. Check your spam folder.
2. Or request a new verification link from the Log In page.

### <mark style="color:$info;">Account Approval Process</mark>

AgeGO uses an Account Status system to control access to the platform and site creation.

Your account can be in one of the following states:

* **Email Not Verified**
  * Newly registered account. Email verification pending.
  * Login is blocked.
* **Not Verified**
  * Email verified but awaiting admin approval.
  * Login allowed.
  * Site creation disabled.
* **Verified**
  * Account verified and approved by an AgeGO Admin.
  * Full access granted, including site creation and configuration.
* **Archived**
  * Account deactivated by Admin.
  * Login blocked.

#### <mark style="color:$primary;">How the Approval Process Works</mark>

{% stepper %}
{% step %}
Email Verification

After email verification, your account enters **Not Verified** status.
{% endstep %}

{% step %}
Account Review

An AgeGO Admin reviews your account.&#x20;

Accounts are usually reviewed within **2 business days**. If your account is still **Not Verified** after that time, contact us at <business@agego.com>.
{% endstep %}

{% step %}
Approval

Once approved, your status changes to **Verified**.

Full access is granted, including the ability to create and manage sites.

You receive an automatic confirmation email.
{% endstep %}
{% endstepper %}

#### <mark style="color:$primary;">Approval Email Notification</mark>

When your account is approved, you will receive an email:

**Subject:** AgeGO: Your account has been approved.

You can then log in to your dashboard, create sites, and start using AgeGO.

Once you're inside the Dashboard:

Create your first site → go to [My Sites](/admin-panel/my-sites)

## <mark style="color:$primary;">Troubleshooting Sign Up</mark>

If you cannot complete the sign up process:

1. **Didn't receive the verification email?** Request a new one from the login page: <https://dashboard.agego.com/reset-password>
2. **Your account is already registered?** Use “Forgot Password” to reset access. <https://dashboard.agego.com/reset-password>
3. **Need to change your email?** Contact <business@agego.com>


# Glossary

This section defines the key roles and terms used throughout the AgeGO documentation.

#### <mark style="color:$info;">AgeGO Business Account</mark>

A business account created to access AgeGO services, configure Sites, and manage integrations. This account is intended for **clients** (businesses) and not for end users.

#### <mark style="color:$info;">Client</mark>

A business, publisher, platform, or service provider that integrates AgeGO as an age-verification solution on their website or application. Clients are responsible for integrating AgeGO and enforcing age restrictions according to applicable regulations.

#### <mark style="color:$info;">Cross-site Automatic Verification</mark>

A mechanism that allows a previously verified user to be recognized across multiple AgeGO-enabled Sites using a secure verification token, reducing the need for repeated age-verification prompts.

#### <mark style="color:$info;">End User</mark>

An individual who visits a website or application that uses AgeGO and is asked to verify their age in order to access age-restricted content or services.

#### <mark style="color:$info;">Returning User</mark>

An end user who has already completed age verification and can be recognized without repeating the full verification flow, depending on the integration and session context.

#### <mark style="color:$info;">Site</mark>

A website or application operated by a Client and integrated with AgeGO.

Each Site is identified by a unique ASI value and represents a single integration context.

#### <mark style="color:$info;">Underage User</mark>

An end user who does not meet the required age threshold and is therefore denied access to age-restricted content or services.

#### <mark style="color:$info;">Verification Flow</mark>

The sequence of steps an end user goes through once age verification is triggered, from the initial prompt to a successful or failed outcome.

#### <mark style="color:$info;">Verification Method</mark>

A specific mechanism used by AgeGO to assess whether an end user meets the required age threshold (for example: selfie-based estimation, credit card verification, or digital identity checks).


# Integration

AgeGO offers two integration paths, depending on the level of control and flexibility you need.

* **Overlay (client-side):** A drop-in JavaScript snippet that renders an overlay on top of your pages and masks content until verification is complete. Fastest to launch, minimal or no backend work.
* **S2S (server-to-server):** A backend workflow where your server decides who and when to send to AgeGO for verification and handles callbacks. Requires development effort but offers maximum flexibility.

## <mark style="color:$primary;">How It Works</mark>

At a high level, both integration paths follow the same logical flow, with differences in how verification is triggered.

{% stepper %}
{% step %}
A visitor requests a page on your site.
{% endstep %}

{% step %}
Your site triggers AgeGO:

* **Overlay**: the JavaScript snippet displays the verification overlay directly on the page.
* **S2S**: your server redirects selected users to AgeGO for verification.
  {% endstep %}

{% step %}
AgeGO performs the configured verification checks (for example: Selfie, Credit Card, SMS).
{% endstep %}

{% step %}
Your site receives the verification result via redirect or callback and:

* grants access, or
* denies access, depending on the result.
  {% endstep %}
  {% endstepper %}

### <mark style="color:$info;">**Languages**</mark>

The AgeGO verification flow is available in English, German, Spanish, French, Italian and Portuguese (Brazil).&#x20;

The language is selected automatically based on the user's browser settings, and users can change it at any time from the language menu.

## <mark style="color:$primary;">Choose Your Integration Path</mark>

When a site is created in the AgeGO Admin Panel, site owners are presented with three integration options under **Integrate AgeGO with your website**:

![](https://content.gitbook.com/content/1v2DbmntPqhCff92tEVb/blobs/kmSl6uz68rb9WsT6txM7/image)

### <mark style="color:$info;">Modal Integration (JavaScript Snippet)</mark>

Recommended for most websites.

* Add one JavaScript snippet.
* AgeGO opens as an overlay.
* No backend setup required.
* Automatic handling of user interface and verification flow.
* Ideal for publishers, platforms, and most online services.

→ [Open Modal Integration Guide](/integration/integration/modal-integration-overlay)

### <mark style="color:$info;">Server-to-Server (S2S)</mark>

Recommended for platforms needing deeper control.

* Backend-driven sequence.
* You manage redirects and session validation.
* Works well for mobile apps, regulated industries, and custom flows.
* Requires handling callbacks and checking verification status.

→ [Open S2S Integration Guide](/integration/integration/s2s-integration)


# Modal Integration (Overlay)

The modal (overlay) integration displays an AgeGO verification window on top of your website when age verification is required.

It allows you to protect age-restricted content without redirecting users away from your site or rebuilding your existing flow.

This approach is designed to be:

* Fast to implement
* Flexible
* Minimal impact on UX

{% hint style="warning" %}
Already integrated with AgeGO? If your snippet loads `.../v1/verify.js`, it continues to work, but we recommend updating to the latest script — see [Updating an Existing Integration](#updating-an-existing-integration).
{% endhint %}

Depending on your needs, you can choose between two integration paths.

## <mark style="color:$primary;">Option 1: Basic Web Integration (Quick Setup)</mark>

This option is recommended if you want a simple, plug-and-play integration with minimal configuration.

### <mark style="color:$info;">How It Works</mark>

* The AgeGO modal is triggered when a user tries to access age-restricted content.
* AgeGO handles the full verification flow inside the modal.
* Once verification is completed, the user can continue browsing your site.

### <mark style="color:$info;">Best For</mark>

* Standard implementations
* Fast go-live
* Minimal frontend customization

This option requires very little setup and is ideal if you don't need to deeply customize the user journey.

<figure><img src="https://1868684549-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1v2DbmntPqhCff92tEVb%2Fuploads%2FwndSNlReylkr95FBVDwD%2FScreenshot%202026-07-21%20at%2018.15.46.png?alt=media&amp;token=6df2fd13-096d-4dc3-aba5-2d79fee49ac7" alt=""><figcaption></figcaption></figure>

Place the snippet from Admin Panel inside the `<body>` tag of any webpage you wish to protect:

**Example:**

{% code overflow="wrap" expandable="true" %}

```html
<!-- AgeGO Age verification -->

<!-- When JavaScript is disabled -->
<noscript>
  <meta http-equiv="refresh" content="0; url=https://myapi.agego.com/noJS"/>
</noscript>

<!-- Age verification -->
<script src="https://verifycdn.agego.com/v2/verify.js"></script>
<script>
  window.AGEGO = window.AGEGO || function () {
    (AGEGO.e = AGEGO.e || []).push(arguments);
  };
    // Initialize the configuration - place this on every page of your site
  AGEGO('init', {
    asi: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', // must be defined
    autoBlur: true, // Set to false if you use your own content-blocking
    requireAgeVerification: true, // Enable/disable age verification option
    overlay: {
      logo: 'https://example.com/logo.png', // Optional custom logo URL. Default: AgeGO logo
      theme: 'auto' // 'auto', 'light', 'dark'
    }
  });
  // Start the verification flow - call only on pages where verification should run
    AGEGO('launch');  
</script>
<!-- END AgeGO Age verification -->
```

{% endcode %}

## <mark style="color:$primary;">Option 2: Advanced Web Integration (More Control)</mark>

This option is recommended if you need more flexibility and tighter control over when and how the modal is triggered.

### <mark style="color:$info;">How It Works</mark>

* You control when the AgeGO modal opens (for example, based on user actions, country detection, or specific pages).
* The verification still happens inside the modal, but the trigger logic is handled on your side.
* This allows you to better align age verification with your existing UX and business logic.

### <mark style="color:$info;">Best For</mark>

* Custom user flows
* Country-based enforcement
* More advanced frontend logic

![](https://1868684549-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1v2DbmntPqhCff92tEVb%2Fuploads%2FGrwvbGby42EicTLdq5Rc%2FScreenshot%202026-07-21%20at%2018.15.21.png?alt=media\&token=75112306-9a2d-4d2d-8bca-93a053befe55)

This option provides greater customization, including event handling, dynamic content, error messaging, and cookie management:

**Example:**

{% code overflow="wrap" expandable="true" %}

```html
<!-- AgeGO Age verification -->

<!-- When JavaScript is disabled -->
<noscript>
  <meta http-equiv="refresh" content="0; url=https://myapi.agego.com/noJS"/>
</noscript>

<!-- Age verification -->
<script src="https://verifycdn.agego.com/v2/verify.js"></script>
<script>
  window.AGEGO = window.AGEGO || function () {
    (AGEGO.e = AGEGO.e || []).push(arguments);
  };
    // Initialize the configuration - place this on every page of your site
  AGEGO('init', {
    asi: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', // must be defined
    userNonce: undefined, // use this value for nonce, instead of generating random.
    callbackToken: undefined, // use this value as callback token that is replaced in the site callback url.
    autoBlur: true, // Set to false if you use your own content-blocking
    redirect: undefined, // use this value to start the normal flow without applying any explicit redirect
    requireAgeVerification: true, // Enable/disable age verification option
    underageRedirectTo: 'https://google.com',
    overlay: {
      logo: 'https://example.com/logo.png', // Optional custom logo URL. Default: AgeGO logo
      theme: 'auto', // 'dark', 'light' or 'auto'
      content: {
        heading: 'Website for adults viewing only!',
        description: 'Enter prompt description content here',
        ctaAgeVerify: {
          cta: 'Verify age',
          label: 'Continue with age verification'
        },
        ctaUnderageSkip: {
          cta: 'I am not 18 years old'
        }
      },
      messages: {
        errors: {
          'nonceInvalid': 'Internal error. Please, try again.',
          'agegoError': 'Age verification failed. Please, try again later.',
          'notVerified': 'Your age could not be verified. Please, try again.',
          'expired': 'Your age verification has expired. Please, try again.',
          'internalError': 'Failed to start age verification process - internal error. Please, try again.'
        }
      }
    },
    cookies: {
      // Cookie where age verification state is persisted
      ageVerifyState: {
        name: 'agego_aver',
        expires: 'session',
        attr: {
          sameSite: 'strict',
          path: '/',
          secure: false,
          domain: '.mysite.com' // Optional. Set a root/parent domain to share verification across all subdomains (e.g. www., fr., de.)
        }
      }
    },
    events: {
      // Called when age verification flow is completed. Can be used for backend verification.
      onVerificationFlowEnd(eventData) {
      },
      // Called when age verification flow failed for any reason.
      onVerificationFlowFailed(error) {
      },
      // Called when user executes age verification CTA.
      onAgeVerify() {
      },
      // Called when user executes underage CTA.
      onUnderageSkip() {
      },
      // Called for returning users, when age was already verified.
      onVerifiedBefore() {
      },
     }
    });
    // Start the verification flow - call only on pages where verification should run
    AGEGO('launch');
</script>
<!-- END AgeGO Age verification -->
```

{% endcode %}

***

## <mark style="color:$primary;">Updating an Existing Integration</mark>

This applies to both Basic and Advanced integrations. If your existing AgeGO snippet loads `.../v1/verify.js` and calls `AGEGO('configure', {...})`, your site uses the previous version of the integration script. It continues to work — you can update at your convenience.

Updating the script gives you more control over where verification runs: `init` registers your configuration on every page, while `launch` starts the flow only on the pages you choose.

The changes required are:

{% stepper %}
{% step %}

#### Change the script URL

In your `<script src="...">` tag, replace `/v1/verify.js` with `/v2/verify.js`.
{% endstep %}

{% step %}

#### Rename configure to init

Replace `AGEGO('configure', {...})` with `AGEGO('init', {...})`. All configuration options stay exactly the same. Place `init` on every page of your site.
{% endstep %}

{% step %}

#### Add launch

Add `AGEGO('launch');` after the `init` call. `init` only registers your configuration — `launch` is what starts the verification flow. Call it only on pages where verification should run.
{% endstep %}
{% endstepper %}

## <mark style="color:$primary;">Configuration Details</mark>

This section describes the configuration options available for the AgeGO modal.

These options apply to both Basic and Advanced integrations and allow you to control how the modal behaves, looks, and interacts with your site once it is triggered.

### <mark style="color:$info;">General Configuration</mark>

* `asi`: A unique identifier that links the AgeGO prompt to your website. You can find this value in the “My Sites” section of the AgeGO admin dashboard.
* `userNonce`: A unique, single-use security value to prevent sharing of verification status between users. Defaults to `undefined`. When `undefined`, it will be generated by the prompt itself and stored in a first-party cookie.
* `callbackToken`: This value is passed back to your site via the callback URL and can be used to match the verification result with your internal logic or session handling.
* `autoBlur`: Controls whether the site content is automatically blurred when the modal is active.
  * Defaults to `true`
  * Set to `false` if you already use your own content-blocking or obfuscation method
* `requireAgeVerification`: If you already use your own content-blocking or obfuscation mechanism, this option allows you to control whether AgeGO age verification is enabled. It determines whether the age-verification call to action (CTA) is displayed and whether the AgeGO verification flow is active.
  * Defaults to `true`
  * `true` → the age-verification CTA is shown and AgeGO verification is enabled
  * `false` → the CTA is hidden and the AgeGO verification flow is disabled

### <mark style="color:$info;">Redirect Behavior (Modal)</mark>

This section describes how users are redirected within the AgeGO modal flow.

These options control where the verification flow starts and where underage users are sent, without leaving the modal-based integration.

`underageRedirectTo`: A URL the visitor is redirected to when the I am not 18 years old CTA is pressed.

`redirect`: The redirect parameter controls where users start their journey when the AgeGO flow begins.

* `myaccount`: When set to `myaccount`, the user is redirected to the My Account page after logging in.
  * If the user is already logged in, they are taken directly to My Account.
  * If the user is not logged in, they are first sent to the login page. After logging in, the flow proceeds to My Account.
  * Verification logic remains unchanged:
    * If the user is not verified, they are redirected to the Verification Methods page.
    * If the user is verified, they proceed normally.
* `login`: When set to `login`, the user is redirected directly to the login page instead of the usual starting page of the flow. After logging in:
  * If the user is not verified, they are sent to the Verification Methods page.
  * If the user is verified, they continue through the standard flow.
* Default value
  * If no value is provided, the user lands on the default starting page of the flow.

### <mark style="color:$info;">Modal Close (X)</mark>

If you manage your own SFW/NSFW content split and only want to require verification for specific pages or actions. For these setups, AgeGO offers an optional Modal Close (X) button on the verification screen, so users can dismiss the modal before verifying and go back to the site's SFW content.

<figure><img src="https://1868684549-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1v2DbmntPqhCff92tEVb%2Fuploads%2FlFFQ6I9xztMRhNi3YpV5%2FScreenshot%202026-08-27%20at%2013.25.01.png?alt=media&amp;token=bd905979-9d8e-4bf0-85ae-43a4591ecdb2" alt="AgeGO age-verification modal showing the close (X) button in its top-right corner."><figcaption></figcaption></figure>

#### **Key points**

* This is a per-site setting, enabled from My Sites → Edit Site in the Dashboard (not a JavaScript configuration option). See the [My Sites section](/admin-panel/my-sites) of this guide for how to enable it.
* It is off by default for every site.
* The close (X) button only appears on the "Verify your age to continue" (method-selection) screen. It is not shown once the user has started a verification method, and not on login/registration screens.
* It applies only to the overlay (modal) integration. It is never shown on S2S integrations, even if the setting is enabled for the site.
* It is not shown during mobile continuation sessions (e.g. QR code hand-off to a phone for selfie or ID capture). The X only appears on the parent session, not the child session.
* Dismissing the modal removes the AgeGO overlay/blur for that page view only. If the user triggers restricted content again, the modal reappears (with the close option, if still enabled).

#### **When to enable this**

Only enable this setting if your site has a content tier that is legally accessible without age verification, and you control the technical separation between that SFW tier and your age-restricted (NSFW) content. Enabling it makes you responsible for ensuring that a user who dismisses the modal cannot reach restricted content, and that your SFW tier complies with the law in every jurisdiction where your users are located. See our [Terms & Conditions for Business Customers](https://www.agego.com/terms-conditions-for-agego-business-customers) for the specific clause covering this.

{% hint style="info" %}
This setting does not change how the JS snippet is configured, there's no new init parameter. It's controlled entirely from the Dashboard.
{% endhint %}

### <mark style="color:$info;">Overlay Options</mark>

These options control the visual elements of the modal.

* Logo: Optional URL to a custom logo displayed inside the AgeGO modal. If not provided, the default AgeGO logo will be used.
* Theme: Controls the visual theme of the modal:
  * `light`
  * `dark`
  * `auto` (matches the user’s system preference)
* Style: Allows you to customize the appearance of the modal, including layout and visual properties.
* Content: Lets you define custom text, such as:
  * Headers
  * CTA labels
  * Informational text
* Messages: Custom error or system messages shown in specific edge cases, helping improve clarity for users.

{% hint style="info" %}
Custom texts set in Content and Messages are shown as provided and are not translated automatically. If your site serves several languages, set them according to your page language.
{% endhint %}

### <mark style="color:$info;">Cookie Options</mark>

`ageVerifyState`: A cookie used to store the user’s age-verification state.

* Default cookie name: `agego_aver`
* Automatically deleted when the browser is closed.
* Helps avoid repeated verification during the same visit

`domain`: Optional. By default, the cookie is set on the current domain only. If your site uses multiple locale or regional subdomains (for example [www.example.com](http://www.example.com) and fr.example.com), set domain to the shared root domain (e.g. .example.com) so the verification cookie is recognized across all of them. This avoids asking returning users to verify again when they move between subdomains of the same site.

### <mark style="color:$info;">Styling</mark>

You can further customize the modal using `overlay.style`. This allows you to:

* Adjust modal appearance
* Override themes
* Customize headers and CTA styles

All styling changes are purely visual and do **not** affect verification logic or security.

**Example:**

{% code overflow="wrap" expandable="true" %}

```javascript
{
  modal: {
    background: '#ffffff',
    text: '#333333'
  },
  header: {
    background: '#f8f8f8'
  },
  ctaAgeVerify: {
    background: '#55a245',
    text: '#ffffff'
  },
  ctaUnderageSkip: {
    text: '#666666'
  }
}
```

{% endcode %}

### <mark style="color:$info;">Prompt Content</mark>

Prompt content configuration object allows you to override labels and text content of the prompt.

**Example:**

{% code overflow="wrap" expandable="true" %}

```javascript
{
  heading: 'Website for adults viewing only!',
  description: 'HTML content to display in the description box of the modal',
  ctaAgeVerify: {
    cta: 'Verify age',
    label: 'Continue with age verification'
  },
  ctaUnderageSkip: {
    cta: 'I am not 18 years old'
  }
}
```

{% endcode %}

### <mark style="color:$info;">Prompt Messages</mark>

Prompt message configuration allows you to customize the messages shown to users during the age-verification flow.

These messages help explain what is happening and provide clear feedback when something goes wrong.

### <mark style="color:$info;">Error Messages</mark>

Error messages are displayed when the verification flow cannot be completed successfully. Each message corresponds to a specific situation.

* `nonceInvalid`: Displayed when the verification session is no longer valid.

  This usually happens when the security nonce used during the flow does not match the value received from AgeGO. For example, this can occur if the page is refreshed or the session is reused.
* `agegoError`: Displayed when an unexpected error occurs during the age-verification process that is not caused by the user.

  This typically indicates a temporary system or service issue.
* `notVerified`: Displayed when the user has not completed age verification or is identified as underage.

  This message informs the user that access cannot be granted.
* `expired`: Displayed when the age-verification callback has expired.

  This is a technical error that usually occurs if the user takes too long to complete the flow or if the session times out.
* `internalError`: Displayed for other undefined technical errors.

  This may include:

  * Network timeouts
  * Connectivity issues
  * Other unexpected system errors

**Example:**

{% code overflow="wrap" expandable="true" %}

```javascript
messages: {
  errors: {
    nonceInvalid: 'Internal error. Please, try again.',
    agegoError: 'Age verification failed. Please, try again later.',
    notVerified: 'Your age could not be verified. Please, try again.',
    expired: 'Your age verification has expired. Please, try again.',
    internalError: 'Failed to start age verification process - internal error. Please, try again.'
  }
}
```

{% endcode %}

### <mark style="color:$info;">Events</mark>

AgeGO exposes a set of events that allow you to hook into key moments of the age-verification flow.

These events can be used to update your UI, trigger analytics, or apply custom business logic.

* `onVerificationFlowEnd`: Triggered when the age-verification process is completed successfully. This event indicates that the user has been verified and can be granted access to age-restricted content.
* `onVerificationFlowFailed`: Triggered when the age-verification process does not complete successfully and the user is not verified. This can happen if the user abandons the flow or if the verification cannot be completed.
* `onAgeVerify`: Triggered when the user interacts with the age-verification call to action (CTA) to start the verification process.
* `onUnderageSkip`: Triggered when the user interacts with the “I am not 18” CTA.
* `onVerifiedBefore`: Triggered when a returning user has already been verified and no new verification is required.


# S2S Integration

The Server-to-Server (S2S) integration allows your backend to fully control when and how users are sent to AgeGO for age verification.

This integration does not require any frontend code and is ideal if you want to manage age verification entirely from your server-side logic, including routing, session handling, and access control.

## <mark style="color:$primary;">When to Use S2S Integration</mark>

S2S is recommended if you:

* Want full backend control over the verification flow.
* Prefer redirects over frontend modals.
* Already manage user sessions and access logic server-side.
* Need a clear separation between your frontend and verification logic.

## <mark style="color:$primary;">High-Level Flow</mark>

At a high level, the S2S integration works as follows:

1. Your backend determines that a visitor requires age verification.
2. Your server redirects the user to AgeGO for verification.
3. The user completes the configured verification checks on AgeGO.
4. AgeGO redirects the user back to your site.
5. Your backend validates the response and grants or denies access accordingly.

## <mark style="color:$primary;">Prerequisites</mark>

Before implementing S2S integration, ensure you have:

* An active AgeGO site configured in the dashboard (Name, Website URL, Callback URL, Site Status).
* Your `asi`.
* An HTTPS endpoint on your side to receive the user after verification.

## <mark style="color:$primary;">Get Your S2S Start URL</mark>

Each AgeGO site has a unique S2S start URL available in the dashboard.

![](https://content.gitbook.com/content/1v2DbmntPqhCff92tEVb/blobs/q12Fn2Bp8J9gqLe681Nv/image)

## <mark style="color:$primary;">Redirecting the User to AgeGO</mark>

When your website determines that a user must be age verified (for example, on first visit or before accessing restricted content), your backend redirects the user to the AgeGO S2S start URL.

This redirect URL is unique per site and supports several query parameters to control security, routing, and user experience.

### <mark style="color:$info;">Redirect Parameters</mark>

* `asi` (mandatory): The unique identifier of your site in AgeGO. This value links the verification request to the correct site configuration.
* `returnto` (optional, recommended): Defines the HTTPS URL where the user is redirected after the age-verification flow completes.
  * When provided, AgeGO redirects the user to this URL after verification.
  * When omitted, AgeGO redirects the user to the root of your Site’s Website URL.
  * When used, this must be a full HTTPS URL pointing to a specific page on your domain.

Using `returnto` is strongly recommended to maintain control over post-verification routing.

**Example with `returnto` :**

{% code overflow="wrap" expandable="true" %}

```
https://myapi.agego.com/s2s/start/?asi=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&returnto=https%3A%2F%2Fwww.example.com%2Fmembers%2Fwelcome
```

{% endcode %}

**Without `returnto` (falls back to Site’s Website URL root):**

{% code overflow="wrap" expandable="true" %}

```
https://myapi.agego.com/s2s/start/?asi=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
```

{% endcode %}

* `nonce`: Optional, a random hexadecimal value that will be sent in return request to prevent session tampering and sharing. This value can be saved with user session and used later to verify the returning visitor has the same session. nonce MUST be 64 characters or less.
* `callbacktoken`: Optional, value that will be replaced in the site callback url {`callbacktoken`}. callbacktoken MUST be 64 characters or less.
* `redirect`: The redirect parameter controls which page the user is sent to when the flow starts. The following values are supported:
  * `myaccount`: When set to myaccount, the user is redirected to the My Account page after logging in.
    * If the user is already logged in, they are taken directly to My Account.
    * If the user is not logged in, they are first sent to the login page. After logging in, the flow proceeds to My Account.
    * Verification logic remains unchanged:
      * If the user is not verified, they are redirected to the Verification Methods page.
      * If the user is verified, they proceed normally.
  * `login`: When set to `login`, the user is redirected directly to the login page instead of the usual starting page of the flow. After logging in:
    * If the user is not verified, they are sent to the Verification Methods page.
    * If the user is verified, they continue through the standard flow.
  * Default value: If no value is provided, the user lands on the default starting page of the flow.

### <mark style="color:$info;">Important Notes</mark>

* Redirect parameters apply only to the Server-to-Server (S2S) integration.
* The hostname used in `returnto` must be whitelisted in your site settings.
* Redirect behavior in S2S differs from the Modal integration.
* If Modal Close (X) is enabled for your site in the Dashboard, it will not show a close button in your S2S integration. This setting only applies to the overlay (modal) integration. In S2S, the verification flow is a redirect, and allowing users to "close" partway through could cause redirect loops, so the close option is intentionally not available in this mode. The toggle can still be saved for a site using S2S, but it has no effect on the flow.

**Example redirect URL:**

**Base redirect URL from My Sites:**

{% code overflow="wrap" %}

```
https://myapi.agego.com/s2s/start/?asi=YOUR_ASI&returnto=YOUR_RETURN_URL&nonce=OPTIONAL_NONCE&callbacktoken={callbacktoken}
```

{% endcode %}

**Redirect URL with the optional `redirect` parameter:**

{% code overflow="wrap" %}

```
https://myapi.agego.com/s2s/start/?asi=YOUR_ASI&returnto=YOUR_RETURN_URL&nonce=OPTIONAL_NONCE&callbacktoken={callbacktoken}&redirect=myaccount
```

{% endcode %}

After verification, the user is redirected back to:

* the URL specified in `returnto` (if provided), or
* the root of your site’s Website URL.

Your backend should:

* Parse the returned query or fragment parameters.
* Verify the integrity of the response (`ag_signature`).
* Validate the `nonce` (if used).
* Map the result to the correct user or session.
* Grant or deny access accordingly.

#### <mark style="color:$primary;">Return Parameters</mark>

The redirect back to your site includes the following GET parameters describing the verification result:

* `ag_error`: Error code, if any (see below for possible error codes).
* `ag_expires`: UNIX timestamp in milliseconds after which this request must be considered as expired.
* `ag_nonce`: Value initially sent with nonce parameter in redirect url, none if no value was sent.
* `ag_verified`: Yes if the visitor was successfully age-verified, no otherwise.
* `ag_verified_site`: unique id of the website the visitor was verified for, must match the id of the site for the asi parameter in the initial request.
* `ag_user_token`: a unique token identifying the verified user.

In addition to above, the following two parameters are sent to verify the information sent with the redirect has not been tampered with and is in fact sent by AgeGO platform.

* `ag_signature`: Checksum of all the values of the previously listed GET parameters.
* `ag_signature_algo`: Hash algorithm used for the signature. Currently, the only possible value for this parameter is sha256, however, in future, a different algorithm might be used - all users will be notified about any signing algorithm changes in advance.

Other optional parameters that might or might not be present in return request:

* `ag_remember_me`: Optional, values yes, or no. Indicates strong user preference to persist the verification result beyond normal session lifetime. Value yes indicates user prefers to persist verification status beyond session lifetime, ex. for 1 year.

### <mark style="color:$info;">Overlay S2S Mode</mark>

Enables server-to-server (S2S) verification mode. When set to true, the AgeGO prompt expects age verification results to be provided via URL query parameters (such as `ag_user_token` and `ag_verified`, or `ag_token`).

It is intended for use cases where verification is handled externally and the result is returned to the frontend, typically through cross-site verification flows or post verification redirects.

If valid parameters are present, the user is considered verified, the `agego_aver` cookie is set with the values from the query parameters, and no overlay or modal is ever shown.

Both `ag_user_token` (with `ag_verified`=yes) and `ag_token` are supported for verification in this mode.

{% hint style="warning" %}
It is not required for standard S2S integrations and should only be used when verification results are returned to the frontend.
{% endhint %}

{% code overflow="wrap" expandable="true" %}

```html
<!-- AgeGO Age verification -->
<script src="https://verifycdn.agego.com/v2/verify.js"></script>
<script>
  window.AGEGO = window.AGEGO || function () {
    (AGEGO.e = AGEGO.e || []).push(arguments);
  };

  AGEGO('init', {
    s2sMode: true,
    // ... other options
  });
  AGEGO('launch');
</script>
```

{% endcode %}

{% hint style="info" %}
If you also need to share the `agego_aver` cookie across subdomains while using s2sMode, the same `domain` configuration described in [Modal Integration → Cookie Options](/integration/integration/modal-integration-overlay#cookie-options) applies.
{% endhint %}

## <mark style="color:$primary;">Verifying the Signature</mark>

All return requests will always be accompanied with `ag_signature` parameter that contains a keyed hash value using HMAC hashing method.

The hash is computed on all values in return request listed below, separated by vertical bar, and in the exact order as specified below:

```csharp
ag_error | ag_expires | ag_nonce | ag_verified | ag_verified_site
```

The secret used to calculate the HMAC can be found in "My Sites" section for each individual site.

### <mark style="color:$info;">Important Security Checks</mark>

* Always verify if `ag_signature_algo` contains the permitted value(s) as documented above.
* A string none is used to indicated default/missing values, for example, for `ag_nonce`, `ag_error` and similar.
* Always verify that `ag_expires` timestamp value is in the future.
* Using `nonce` is not mandatory but is recommended to prevent sharing of the verification URL.
* Keep your site secret value private and not accessible in frontend code. Leaked site secret will allow for anyone to impersonate age verification responses and bypass the verification process.

## <mark style="color:$primary;">Possible Error Codes</mark>

* `none`: Indicates no error.
* `suspended`: The site is suspended or inactive. [Contact Support](/support/support) if you think this is an error.

### <mark style="color:$info;">Code Examples for Signature Calculation</mark>

Minimal code examples to illustrated signature verification process of the return request.

**PHP**

{% code overflow="wrap" expandable="true" %}

```php
$data = sprintf(
    '%s|%s|%s|%s|%s',
    $query['ag_error'],
    $query['ag_expires'],
    $query['ag_nonce'],
    $query['ag_verified'],
    $query['ag_verified_site']
);

$expectedSignature = hash_hmac('sha256', $data, $siteSecret);

$status = $query['ag_signature'] === $expectedSignature;

// TODO: check if $status === true
```

{% endcode %}

**Python**

{% code overflow="wrap" expandable="true" %}

```python
import hmac
import hashlib

if query.ag_signature_algo == 'sha256':
    algo = hashlib.sha256
else:
    raise Exception('Invalid hash algorithm')

data = '%s|%s|%s|%s|%s' % (
    query.ag_error,
    query.ag_expires,
    query.ag_nonce,
    query.ag_verified,
    query.ag_verified_site
)

status = hmac.new(site_secret, data, algo).hexdigest() == query.ag_signature

# TODO: check if status == True
```

{% endcode %}

**NodeJs**

{% code overflow="wrap" expandable="true" %}

```js
const crypto = require('crypto');

const data =
  query['ag_error'] + '|' +
  query['ag_expires'] + '|' +
  query['ag_nonce'] + '|' +
  query['ag_verified'] + '|' +
  query['ag_verified_site']
;

const hmac = crypto.createHmac(signatureAlgo, siteSecret);
hmac.update(data);
const status = hmac.digest('hex') === query['ag_signature'];

// TODO: check if status === true
```

{% endcode %}

**Ruby**

{% code overflow="wrap" expandable="true" %}

```ruby
require 'openssl'

data = "#{query['ag_error']}|" \
       "#{query['ag_expires']}|" \
       "#{query['ag_nonce']}|" \
       "#{query['ag_verified']}|" \
       "#{query['ag_verified_site']}"

digest = OpenSSL::Digest.new(signature_algo)

status = OpenSSL::HMAC.hexdigest(digest, site_secret, data) == signature

# TODO: check if status === true
```

{% endcode %}

## <mark style="color:$primary;">Validating</mark> <mark style="color:$primary;">`ag_user_token`</mark> <mark style="color:$primary;">with the AgeGO API</mark>

```
POST https://myapi.agego.com/authorization/user/validate-token
```

Use the `ag_user_token` returned by the S2S callback as the value of `token`.

**Request body (JSON)**

<table data-header-hidden><thead><tr><th width="186.06158447265625" align="center"></th><th width="130.00439453125" align="center"></th><th align="center"></th></tr></thead><tbody><tr><td align="center"><mark style="color:$primary;">Parameter</mark></td><td align="center"><mark style="color:$primary;">Required</mark></td><td align="center"><mark style="color:$primary;">Description</mark></td></tr><tr><td align="center">token</td><td align="center">Yes</td><td align="center">JWT returned after successful verification.</td></tr><tr><td align="center">country</td><td align="center">Optional</td><td align="center">ISO 3166-1 alpha-2 country code (e.g. "DE").</td></tr><tr><td align="center">region</td><td align="center">Optional</td><td align="center">ISO 3166-2 subdivision code without the country prefix (e.g. "FL" for Florida/US) — Requires country</td></tr></tbody></table>

When `country` is provided (optionally with `region`), the token is also validated against the user's verification methods for that location.

Call this endpoint when a returning verified user accesses your site and you need to confirm the token is still valid for their current location.

{% hint style="warning" %}
Publishers must not replicate AgeGO's location-validity logic on their side. All location-eligibility checks must go through this endpoint.
{% endhint %}

**Responses**

<table data-header-hidden><thead><tr><th width="89.64068603515625" align="center"></th><th width="159.58331298828125" align="center"></th><th width="500.161376953125" align="center"></th></tr></thead><tbody><tr><td align="center"><mark style="color:$primary;">Status</mark></td><td align="center"><mark style="color:$primary;">Response Body</mark></td><td align="center"><mark style="color:$primary;">Description</mark></td></tr><tr><td align="center">200</td><td align="center">{ "status": true, "message": "Valid token" }</td><td align="center">Token is valid. When country is provided, the verification methods are also accepted for that location</td></tr><tr><td align="center">200</td><td align="center">{ "status": false, "error": "..." }</td><td align="center"><p>Where "..." is one of:</p><p><code>Invalid token</code> — signature invalid or token expired</p><p><code>Invalid token structure</code> — token is missing required claims</p><p><code>User invalid</code> — the user was not found, has logged out or been deleted</p><p><code>No valid verification method for country/region</code> — verification method isn't accepted in the supplied location</p></td></tr><tr><td align="center">400</td><td align="center">{ "status": false, "error": "..." }</td><td align="center">Where "..." is one of:<br><code>No token provided</code> — The request is malformed (missing token)<br><code>Country is required when region is provided</code> — region supplied without country.</td></tr><tr><td align="center">500</td><td align="center">{ "status": false, "error": "Validation failed" }</td><td align="center">Server error during validation</td></tr></tbody></table>

### <mark style="color:$info;">Code Examples for Validating</mark> <mark style="color:$info;">`ag_user_token`</mark> <mark style="color:$info;">with the AgeGO API</mark>

Minimal code examples to illustrate user token validation process using AgeGO API.

**PHP**

{% code overflow="wrap" expandable="true" %}

```php
$url = 'https://myapi.agego.com/authorization/user/validate-token';
$token = 'your-jwt-token-here';

$data = json_encode([
'token' => $token,
'country' => 'DE', // optional
'region' => 'BY'   // optional
]);

$ch = curl_init();

curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_HTTPHEADER => [
  'Content-Type: application/json',
  'Content-Length: ' . strlen($data)
],
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

echo "HTTP Code: $httpCode\n";
echo "Response: $response\n";

$decodedResponse = json_decode($response, true);
if ($decodedResponse['status']) {
  echo "Token is valid\n";
} else {
  echo "Token validation failed: " . $decodedResponse['error'] . "\n";
}

curl_close($ch);
```

{% endcode %}

**NodeJs**

{% code overflow="wrap" expandable="true" %}

```js
const https = require('https');

const url = 'https://myapi.agego.com/authorization/user/validate-token';
const token = 'your-jwt-token-here';

const data = JSON.stringify({
token: token,
country: 'DE', // optional
region: 'BY'   // optional
});

const options = {
method: 'POST',
headers: {
  'Content-Type': 'application/json',
  'Content-Length': Buffer.byteLength(data)
}
};

const req = https.request(url, options, (res) => {
let responseData = '';

res.on('data', (chunk) => {
  responseData += chunk;
});

res.on('end', () => {
console.log(`HTTP Code: ${res.statusCode}`);
console.log(`Response: ${responseData}`);

try {
  const decodedResponse = JSON.parse(responseData);
  if (decodedResponse.status) {
    console.log('Token is valid');
  } else {
    console.log('Token validation failed');
  }
} catch (error) {
  console.log('Error parsing response:', error.message);
}
});
});

req.write(data);
req.end();
```

{% endcode %}


# Geolocation

This guide explains how to detect a user’s country and decide when AgeGO should be triggered based on geographic and regulatory requirements.

The solution supports:

* One country
* Multiple countries
* A clear fallback logic when detection fails

## <mark style="color:$primary;">Overview</mark>

AgeGO can be triggered only for users coming from specific countries, while users from other countries can access the content directly.

This setup allows you to:

* Enforce age verification only where legally required
* Reduce friction in countries where age verification is not mandatory
* Use a single implementation for multiple geographies

You define:

* Which country or countries require AgeGO
* Which AgeGO `asi` should be used for your domain

## <mark style="color:$primary;">Prerequisites</mark>

Before implementing this logic, make sure you have:

* An active AgeGO account
* Your AgeGO `asi` (alpha-numeric)
* A country detection method, such as:
  * Server-side geolocation
  * Client-side IP-based country detection
  * A CMP or analytics tool providing country code

Country codes must follow **ISO 3166-1 alpha-2 format**, for example:

* IT (Italy)
* FR (France)
* ES (Spain)
* DE (Germany)

Hide content of the web page:

```routeros
<div id="general" style="display:none;">
```

## <mark style="color:$primary;">Implementation / SetUp</mark>

#### <mark style="color:$info;">**HTML Structure**</mark>

Wrap all content that should be gated by logic inside `#general` and keep it hidden initially.

{% code overflow="wrap" expandable="true" %}

```html
<div id="general" style="display:none;"> //hides content
  <section class="section bg-light">
    <div class="container">
      <h2>Ad Section</h2>
      <p class="small">Banner</p>
      <script async type="application/javascript" src="https://test.example.com/ad-provider.js"></script>
      <ins class="eas6a97888e2" data-zoneid="5759198"></ins>
      <script>(AdProvider = window.AdProvider || []).push({ "serve": {} });</script>
    </div>
```

{% endcode %}

#### <mark style="color:$info;">**Javascript Disable Fallback**</mark>

Redirect users with disabled JavaScript.

{% code overflow="wrap" expandable="true" %}

```html
<!-- ...existing code... -->
<noscript>
  <meta http-equiv="refresh" content="0; url=https://myapi.agego.com/noJS" />
</noscript>
<!-- ...existing code... -->
```

{% endcode %}

#### <mark style="color:$info;">**Country Detection and Conditional Logic**</mark>

{% code overflow="wrap" expandable="true" %}

```html
<script>
  async function loadCountryLogic() {
    let countryCode = localStorage.getItem('userCountry');

    if (!countryCode) {
      try {
        const res = await fetch('https://get.geojs.io/v1/ip/country.json');
        const data = await res.json();
        countryCode = data.country || 'unknown';
        localStorage.setItem('userCountry', countryCode);
      } catch (err) {
        console.warn('GeoJS API failed, trying fallback...');
        try {
          const res2 = await fetch('https://ipapi.co/json/');
          const data2 = await res2.json();
          countryCode = data2.country_code || 'unknown';
          localStorage.setItem('userCountry', countryCode);
        } catch (err2) {
          console.warn('All geo APIs failed, using browser language.');
          const lang = navigator.language || navigator.userLanguage;
          countryCode = (lang && lang.includes('-')) ? lang.split('-')[1] : 'unknown';
        }
      }
    }

    console.log('Detected country:', countryCode);

    if (countryCode === 'IT') {
      // Example for multiple countries:
      const targetCountries = ['IT', 'FR', 'DE', 'ES', 'GB'];

      if (targetCountries.includes(countryCode)) {
        runAgeGoVerification(countryCode);
      } else {
        showAdsDirectly(countryCode);
      }

      function runAgeGoVerification(countryCode) {
        const general = document.getElementById('general');
        if (general) general.style.display = 'block';

        const script = document.createElement('script');
        script.src = "https://verifycdn.agego.com/v2/verify.js";
        script.onload = function () {
          window.AGEGO = window.AGEGO || function () { (AGEGO.e = AGEGO.e || []).push(arguments) };
          AGEGO('init', {
            asi: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', // replace with your AgeGO asi
            autoBlur: true,
            verifyMode: 'inline',
            requireAgeVerification: true,
            allowDirectContinue: false,
            underageRedirectTo: 'https://google.com',
            overlay: {
              logo: '',   // Add a link to your logo image to be shown in AgeGO widget
              theme: 'auto'
            }
          });
          AGEGO('launch');
        };
        document.head.appendChild(script);
      }

      function showAdsDirectly(countryCode) {
        const general = document.getElementById('general');
        if (general) general.style.display = 'block';
      }
    }
  }

  loadCountryLogic();
</script>
```

{% endcode %}

## <mark style="color:$primary;">**Recommended Geolocation Priority**</mark>

If you do not already have a country detection solution, we recommend using the following priority:

1. IP-based geolocation via geojs.io (primary)
2. IP-based geolocation via ipapi.co (fallback)
3. Browser language (last fallback only)

The first valid country code detected should be used.

**Note:** Browser language is less reliable and should only be used when IP-based methods are not available.

## <mark style="color:$primary;">Important Notes About</mark> <mark style="color:$primary;"></mark><mark style="color:$primary;">`asi`</mark>

1. The asi is an alpha-numeric identifier provided by AgeGO
2. It identifies your domain and configuration
3. It is not related to the country

{% hint style="info" %}
The same site ID can be used for one or multiple countries.
{% endhint %}

{% hint style="warning" %}
Country code and site ID are not the same thing.
{% endhint %}

## <mark style="color:$primary;">Testing the Integration</mark>

You can simulate different countries during testing in Google Chrome DevTools - Console.

Simulate an enforced country

```javascript
localStorage.setItem('userCountry', 'IT');location.reload();
```

Simulate a non-enforced country

```javascript
localStorage.setItem('userCountry', 'US');location.reload();
```

Reset the browser's memory

```jboss-cli
localStorage.clear();location.reload();
```

## <mark style="color:$primary;">Key Notes & Best Practices</mark>

* Always use ISO country codes
* Keep country enforcement configurable, not hardcoded
* Use comma-separated values for scalability
* Make sure the same site ID is used consistently per domain
* Country detection should happen before loading AgeGO

## <mark style="color:$primary;">Summary</mark>

* AgeGO can be conditionally enforced by country
* One or multiple countries are supported
* Configuration is simple and scalable
* The same logic works for all markets

This approach allows you to remain compliant while maintaining the best possible user experience.


# Callbacks & Redirects

Learn how to receive the verification result after a user completes the AgeGO flow.

This guide explains how your site receives the verification result via redirect/callback and grants or denies access accordingly.

AgeGO always follows the same high-level principle:

1. A visitor requests a page on your site.
2. You trigger AgeGO (Overlay or S2S).
3. AgeGO performs the configured Checks (e.g. Selfie, Credit Card, SMS, etc).
4. Your site receives the result and handles access.

## <mark style="color:$primary;">Overview</mark>

Depending on your integration method, the “callback” mechanism is different:

**Modal (Overlay), callback events:** With the Overlay integration, the verification flow runs in-page and your site can react through modal callback events (JavaScript events).

**S2S, redirect back to your site:** With **S2S (server-to-server)**, your server redirects selected users to AgeGO for verification and then receives the result when AgeGO redirects the user back to your site.

## <mark style="color:$primary;">Modal Callback Events</mark>

Use modal events to know what happened in the verification flow (for example, success, failure, underage selection, or returning verified users).

This is the recommended approach for handling “callbacks” in Modal integrations.

Typical uses:

1. Unlock content when verification succeeds.
2. Show an error state when verification fails.
3. Route underage users to an alternative page/experience.
4. Skip unnecessary prompting for returning verified users.

*(Implementation details and the exact event names live in the* [*Modal Integration guide*](/integration/integration/modal-integration-overlay#events)*)*

## <mark style="color:$primary;">**S2S Callback via Redirect Back to Your Site**</mark>

### <mark style="color:$info;">**Where the User Returns**</mark>

In S2S, your backend starts verification by redirecting the user to the AgeGO start endpoint.

After verification completes, AgeGO redirects the user back to:

1. The URL in `returnto` (if provided), or
2. The root of your Site’s Website URL (fallback behavior).

### <mark style="color:$info;">**S2S Callback Endpoint**</mark>

Your callback endpoint is simply the page/route on your domain that receives the redirect back from AgeGO (commonly the `returnto` URL).

Your backend should parse the returned parameters, validate them, and decide whether to grant or deny access.

#### <mark style="color:$primary;">Example payloads (what you receive)</mark>

* **S2S return parameters (redirect back to your site)**

After successful or failed verification, the `returnto` URL is modified with GET parameters containing the user status and verification state.

Common fields include:

1. `ag_error`: Error code, if any.
2. `ag_expires`: UNIX timestamp in milliseconds after which the request is expired.
3. `ag_nonce`: The original nonce value (or none).
4. `ag_verified`: yes If successfully verified, otherwise no.
5. `ag_verified_site`: Must match the site used in the initial request (asi).
6. `ag_user_token`: The unique token identifying the verified user.

Integrity fields:

1. `ag_signature`: Checksum of the returned values.
2. `ag_signature_algo`: The algorithm used (e.g. sha256).

*(Full validation logic and code examples live in the S2S guide.)*

## <mark style="color:$primary;">When Callbacks Fire (Success, Cancel, Timeout)</mark>

At a high level, your site should expect a “result” whenever the flow ends in one of these ways:

* Success: the user completes verification successfully.
* Failure / not verified: the user fails verification or does not complete it.
* Underage selection: the user chooses the “I am not 18 years old” CTA (Modal).
* Technical error: network or system error (Modal message / S2S error parameter).
* Timeout / expired: the verification callback expires (S2S uses an expiry timestamp; modal can show an “expired” message).

*(Exact event names and error strings are defined in your Modal “*[*Prompt Messages / Error Messages*](/integration/integration/modal-integration-overlay#prompt-messages)*” and S2S “*[*Possible error codes*](/integration/integration/s2s-integration#possible-error-codes)*” sections.)*

## <mark style="color:$primary;">**How to Avoid Redirect Loops**</mark>

Redirect loops usually happen when a user is sent to AgeGO again immediately after returning to your site.

Recommended safeguards:

**1) Check verified state before triggering again:** If the user is already verified, do not re-trigger the flow. For S2S, use the returned verification status (`ag_verified`) and your own session state.

**2) Use a `nonce` (recommended):** A `nonce` helps you correlate the return response to a specific session and reduce replay/sharing issues.

**3) Respect expiration:** If the response is expired (`ag_expires`), treat it as invalid and restart the flow only when needed.

**4) Store “verification completed” in your session:** Once a user returns verified, persist that state server-side (S2S) or client-side (Modal) so you don’t trigger again on every page load.

## <mark style="color:$primary;">**Related Guides**</mark>

* [Modal Integration Guide](/integration/integration/modal-integration-overlay) → Events, Prompt Messages, Error Messages.
* [S2S Integration Guide](/integration/integration/s2s-integration) → Return Parameters, Signature Verification, Error Codes, Code examples.


# Verification Methods

Age verification on websites is performed using **AgeGO’s verification methods**.

Each method is designed to determine either a user’s **exact age** or whether they fall within a **specific age range** (for example, 18+), depending on regulatory and business requirements.

An overview of all available methods can be found on the [Age Verification Methods](https://www.agego.com/verification-methods) page.

Based on regulation and overall verification performance, AgeGO selects the verification method that best balances compliance and user experience.

{% hint style="info" %}
**Desktop users without a camera**

If a camera-based method is started on a desktop without a camera, AgeGO lets the user continue that step on their mobile device by scanning a QR code. Once completed on mobile, the desktop session continues automatically. No additional integration is required.
{% endhint %}

## <mark style="color:$primary;">Method 1: Selfie</mark>

This method uses a **selfie-based age estimation** to assess a user’s age.

In some cases, an additional **government-issued photo ID** may be required to increase confidence or meet regulatory expectations.

## <mark style="color:$primary;">Method 2: Selfie + ID</mark>

This method combines a **live selfie** (with liveness detection) and a mandatory **government-issued photo ID** to fully verify a user’s age.

## <mark style="color:$primary;">Method 3: Credit Card</mark>

This method uses **credit card authorization** to confirm that a user is **18 years old or over**.

## <mark style="color:$primary;">Method 4: Digital ID</mark>

This method relies on a **third-party digital identity application**, such as **Yoti Digital ID**.

Requirements:

1. A smartphone or webcam.
2. A government-issued photo ID.

## <mark style="color:$primary;">Save Your Verification (New Users)</mark>

Once a user has successfully verified their age with any of the methods listed above, AgeGO displays the **Save Your Verification** screen before they continue to your website.

Saving the verification creates an AgeGO account, so the user can confirm their verified status on future visits without repeating the full verification process, see [Log In](#agego-log-in-returning-users) below.

The user can save their verification with:

* **Passkey** – set up a passkey on their device
* **Google** – link their Google account
* **Email** – enter their email address and confirm a one-time code

Or select **Skip For Now** to go straight to your website. In that case, age verification will be required again on their next visit.

{% tabs %}
{% tab title="Passkey" %}
The passkey flow depends on the device the user verified on.

**On a mobile device**

* The user taps **Passkey**.
* The device’s native passkey prompt appears.
* Once confirmed, the user continues to your website.

**On a desktop**

* The user clicks **Passkey**.
* A QR code is displayed. The user scans it with their mobile device.
* The AgeGO page opens on the mobile device and the native passkey prompt appears.
* Once confirmed on mobile, the user continues to your website.

If the passkey isn’t created for any reason, the user can try again, generate a new QR code, or select **Skip For Now** and continue to your website.

{% hint style="info" %}
A passkey can also be added later from the user’s My Account page.
{% endhint %}
{% endtab %}

{% tab title="Google" %}

* The user selects **Google**.
* The user signs in with their Google account.
* The Google account is linked to the user’s AgeGO profile and the user continues to your website.
  {% endtab %}

{% tab title="Email" %}

* The user enters their email address and selects **Continue**.
* A one-time AgeGO code is sent to the provided email address.
* The user enters the received code.
* The verification is saved and the user continues to your website.
  {% endtab %}
  {% endtabs %}

## <mark style="color:$primary;">Log In (Returning Users)</mark>

Once a user has verified their age and saved their verification, they can log in on subsequent visits to confirm their previously verified status without repeating the full verification process.

When a user visits a website that uses AgeGO, they select “**Log In**” on the age-verification home screen.

The user can log in with:

* **Passkey** – if previously set up
* **Google** – the Google account linked to their AgeGO profile
* **Email** – a one-time code sent to their email address

{% tabs %}
{% tab title="Passkey" %}

* The user selects **Passkey**.
* **On mobile:** the device’s native passkey prompt appears.
* **On desktop:** the **Log In With Passkey** screen opens with a QR code. The user scans it with the mobile device that holds their AgeGO passkey and confirms the prompt there.
* Access to your website is granted.
  {% endtab %}

{% tab title="Google" %}

* The user selects **Google**.
* The user signs in with the Google account linked to their AgeGO profile.
* Access to your website is granted.
  {% endtab %}

{% tab title="Email" %}

* The user enters their email address and selects **Continue**.
* A one-time AgeGO code is sent to the provided email address.
* The user enters the received code.
* Access to your website is granted.
  {% endtab %}
  {% endtabs %}


# Privacy & Cookies

AgeGO uses cookies to support the verification flow and user experience, in line with applicable privacy regulations.

More information is available here: <https://www.agego.com/cookies-policy>

For information about the company operating AgeGO and how verification data is processed and retained, see our [Privacy Policy](https://www.agego.com/privacy-policy).


# Cross Site Verification

This guide explains how AgeGO allows verified users to be automatically recognized across multiple AgeGO-enabled sites.

It covers how verified links work, how verification tokens are generated, and how to implement cross-site verification securely and respecting regulations.

## <mark style="color:$primary;">Overview</mark>

AgeGO Cross-Site Automatic Verification allows users who have already verified their age on one AgeGO-enabled site (Site A) to be automatically recognized as verified when they click on a link going to another AgeGO-enabled site (Site B).

It is designed to reduce repeated verification prompts while staying compliant and privacy-friendly.

This mechanism uses a short-lived, single-use verification token called `ag_token`. Tokens are prepared in the background and attached to the destination URL when the user clicks through; if the prepared token has already expired by then, a fresh one is generated at the moment of the click. Site B must also run the AgeGO script, since it is the script on Site B that reads and validates the token.

How the token gets attached depends on your setup. If the link is served by an AgeGO partner such as ExoClick, the partner's ad script handles it and nothing is needed on your side (partner integration). If you build the links yourself, you use the AgeGO JavaScript helpers to attach the token, and you call `AGEGO('prefetchToken')` once on page load so the first click does not have to wait for one (manual integration, see [Option 2](#option-2-manual-integration)).

## <mark style="color:$primary;">Why This Matters</mark>

Using verified links helps:

* Prevent repeated age-verification flows.
* Reduce friction for returning users.
* Maintain regulatory compliance across linked sites.
* Preserve user privacy (no third-party cookies involved).

## <mark style="color:$primary;">Key Benefits</mark>

* **Robust by design**: The verification status is not passed as “trust me.” It is validated server-side through AgeGO.
* **Short-lived**: Tokens expire after a few minutes, so they are only useful around the click-through moment.
* **No cookies required**: This mechanism does not rely on third-party cookies and can thus be used in cookie-restricted or incognito/private browsing environments.
* **Hard to bypass:** Tokens are single-use and validated by AgeGO servers. Even if copied, they expire quickly and cannot be reused after validation.

## <mark style="color:$primary;">What is a Verified Link?</mark>

A verified link is a standard website link that includes an AgeGO Verification Token (`ag_token`).

**Example:**

```dts
https://site-b.example/page?ag_token=...
```

When a verified user clicks through from Site A to Site B, the AgeGO script on Site B reads and validates the token. If valid, the user is granted access without repeating verification.

{% hint style="warning" %}
If Site B uses a Server-to-Server integration, the AgeGO script may need to be loaded in `s2sMode` so the frontend can read and validate `ag_token` from the URL. See **S2S Integration →** [**Overlay S2S Mode**](/integration/integration/s2s-integration#overlay-s2s-mode).
{% endhint %}

## <mark style="color:$primary;">How It Works (High-Level)</mark>

{% stepper %}
{% step %}
User verifies on Site A.
{% endstep %}

{% step %}
While the page loads, the AgeGO script (or the partner ad script) requests a verification token in the background, so one is ready before any click happens.
{% endstep %}

{% step %}
User clicks a link or ad going to Site B.
{% endstep %}

{% step %}
The ready token is appended to the destination URL as `ag_token`. If no valid token is available at that moment (for example it has expired or was already used), a new one is generated at the moment of the click.
{% endstep %}

{% step %}
From Site B, AgeGO validates the token.
{% endstep %}

{% step %}
If valid, user is instantly recognized as verified.
{% endstep %}
{% endstepper %}

Tokens are single-use: once one is consumed, a new one is prepared in the background for the next click. If a token cannot be obtained in time, the user is redirected normally without one — the click is never blocked — and verifies on Site B as usual.

## <mark style="color:$primary;">Security Design</mark>

Cross-site Automatic Verification includes several security safeguards:

* **Not proof of age**: The token itself is not the proof of age. It’s a secure, single-use “ticket” that allows Site B to fetch verification status from AgeGO.
* **Single-use**: Once successfully validated, the token is immediately invalidated and cannot be used again.
* **Short TTL**: Tokens expire after a few minutes, making them useless if copied and passed to another user.
* **Fresh generation**: Tokens are prefetched in the background as the page or ad loads, or generated at click time, and are only held briefly in the browser — never stored long-term.
* **No third-party cookies**: Does not depend on cross-site cookies or third-party tracking.

## <mark style="color:$primary;">Implementation Options</mark>

AgeGO supports two implementation options for cross-site verification. Choose the one that best fits your setup.

* If you work with an AgeGO partner integration (e.g. ExoClick), start with Option 1: Automatic Integration.
* If you want to create verified links yourself, start with Option 2: Manual Integration. This option includes two approaches:
  * Option A for the simplest setup.
  * Option B for advanced or dynamic use cases.

No demo environment is required.

All examples can be tested directly on your staging or production environment.

### <mark style="color:$info;">Option 1: Automatic Integration (Recommended)</mark>

#### <mark style="color:$primary;">Who is This For?</mark>

Publishers using partner ad networks with direct AgeGO integration, such as ExoClick.

#### <mark style="color:$primary;">How Does it Work?</mark>

* No manual implementation is required.
* AgeGO and ExoClick handle everything automatically.

#### <mark style="color:$primary;">What Happens Behind the Scenes?</mark>

{% stepper %}
{% step %}
A partner ad is displayed on your site.
{% endstep %}

{% step %}
The partner script requests a verification token in the background while the ad is displayed.
{% endstep %}

{% step %}
The user clicks on the ad.
{% endstep %}

{% step %}
The script adds the ready token to the ad’s destination URL — or generates one at the moment of the click if no valid token is available.
{% endstep %}

{% step %}
The user is redirected as usual.
{% endstep %}
{% endstepper %}

#### <mark style="color:$primary;">Do I Need to Enable This?</mark>

* No — Cross-Site Automatic Verification is **enabled by default** for all AgeGO sites. No action is needed on your side.

{% hint style="info" %}
If you would like this feature disabled for one of your sites, contact your AgeGO account manager.
{% endhint %}

### <mark style="color:$info;">Option 2: Manual Integration</mark>

Use this option when you want to create verified links yourself, without relying on an automatic partner integration.

Within the manual approach, AgeGO supports two implementation patterns, depending on how much control you need. AgeGO provides simple JavaScript functions to support this.

Whichever pattern you use, call `AGEGO('prefetchToken')` once on pages that contain verified links. This prepares a token in the background and keeps it fresh while the user is on the page, so the token is ready at click time. Without it, the first click waits briefly for a token to be created (up to 1.5 seconds by default) before redirecting.

```javascript
AGEGO('init', { /* ... */ });
AGEGO('launch');
AGEGO('prefetchToken'); // on pages with verified links
```

#### <mark style="color:$primary;">Option A: All-in-One Automatic Redirect (Easiest)</mark>

**Who is this for?**

Publishers who want the simplest and safest implementation.

**What this does**

{% stepper %}
{% step %}
Generates the verification token.
{% endstep %}

{% step %}
Appends it to the destination URL.
{% endstep %}

{% step %}
Redirects the user automatically.
{% endstep %}
{% endstepper %}

All in one step.

An optional parameter, `openInNewTab`, controls how the redirect is opened. By default, it is set to false, meaning the redirect occurs in the current tab. If set to true, the redirect will open in a new browser tab.

**Example:Button:**

{% code overflow="wrap" %}

```hsp
<button onclick="window.AGEGO('redirectToVerified', 'https://site-b.example')">       Go to Site B (Open the same tab)</button>
```

{% endcode %}

{% code overflow="wrap" %}

```livecodeserver
<button onclick="window.AGEGO('redirectToVerified', 'https://site-b.example', true)">       Go to Site B (Open a new tab)</button>
```

{% endcode %}

**Example Link:**

{% code overflow="wrap" %}

```livecodeserver
<a href="#" onclick="window.AGEGO('redirectToVerified', 'https://site-b.example'); return false;">    Go to Site B (Open the same tab)</a>
```

{% endcode %}

{% code overflow="wrap" %}

```livecodeserver
<a href="#" onclick="window.AGEGO('redirectToVerified', 'https://site-b.example', true); return false;">    Go to Site B (Open a new tab)</a>
```

{% endcode %}

**Key Benefits**

* Only the destination URL needs to be replaced.
* Ideal for “Continue”, “Enter”, or “Visit Site” buttons.
* Recommended for most publishers.

#### <mark style="color:$primary;">Option B: Token-Only Generation (Advanced)</mark>

**Who is this for?**

Publishers with:

1. Custom JavaScript logic.
2. Dynamic pages.
3. Multiple verified links per page.

**How it works**

{% stepper %}
{% step %}
Your site requests a verification token from AgeGO.
{% endstep %}

{% step %}
The token is added to the destination URL.
{% endstep %}

{% step %}
The user is redirected to the destination.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
If you only need the destination URL with the token attached, `AGEGO('getTokenUrl', url)` does steps 1 and 2 for you: it resolves to `url` with `ag_token` appended, or to `url` unchanged if no token could be obtained, and never rejects.
{% endhint %}

**Example JavaScript:**

{% code overflow="wrap" expandable="true" %}

```javascript
<script>
  document.addEventListener('click', async function (e) {
    const target = e.target.closest('.manual-verify');
    if (target) {
      e.preventDefault();

      const destination = target.href || target.getAttribute('data-href');
      if (!destination) return;

      try {
        const data = await window.AGEGO('getVerificationToken');

        if (data && data.token) {
          const url = new URL(destination);
          url.searchParams.set('ag_token', data.token);
          window.location.href = url.toString();
        } else {
          window.location.href = destination;
        }
      } catch (error) {
        console.warn("AgeGO token failed, redirecting normally.", error);
        window.location.href = destination;
      }
    }
  });
</script>
```

{% endcode %}

**Implementation href and button**

{% code overflow="wrap" expandable="true" %}

```html
<a href="https://site-b.example/page1" class="manual-verify">
  Go to Site B (Manual Implementation)
</a>

<button id="manual-verify" class="btn btn-primary">
  Go to Site B (Manual Implementation)
</button>
```

{% endcode %}

In this example, the publisher’s script:

1. Requests a verification token from AgeGO.
2. Appends the token to the destination URL if available.
3. Redirects the user accordingly.

{% hint style="info" %}
If token generation fails, the user is redirected normally without interruption.
{% endhint %}

#### <mark style="color:$primary;">Important: Intermediate Redirects</mark>

{% hint style="warning" %}
If your link passes through one or more intermediate redirects before reaching the final destination:

**The `ag_token` must always be preserved.**

**✅ Correct flow:** Site A → Site B → Site C (token preserved).

**❌ Incorrect flow:** Site A → Site B (token lost).

Losing the token invalidates the verification.
{% endhint %}


# Dashboard

The AgeGO Dashboard provides a central interface to monitor, configure, and manage all aspects of your age-verification activity.

From the Dashboard, you can:

* Review verification performance and trends.
* Manage your sites and integration settings.
* Track usage and costs.
* Access billing and invoices.

This section gives an overview of the main areas of the Dashboard and explains how to use them effectively.

![Admin Panel Overview](https://content.gitbook.com/content/1v2DbmntPqhCff92tEVb/blobs/w24X3LzRi4vbjH4xIn4V/image)

## <mark style="color:$primary;">Dashboard Overview</mark>

The Dashboard tab provides a quick snapshot of your AgeGO account and recent verification activity.

It is designed to give you a high-level view of account status and performance without needing to dive into detailed reports.

On the Dashboard, you will find:

* **Account Status**\
  Indicates whether your account is active and ready to use.
* **Verification Metrics (last 7 days)**\
  A summary of recent verification activity across all your sites:
  * **Sessions**: Number of verification sessions initiated by users.
  * **Accesses**: Number of successful verifications that granted access.
  * **Pass Rate**: Percentage of users who successfully passed verification.
* **Bar Graph**\
  A visual representation of selected metrics (Sessions, Accesses, or Pass Rate) over time, allowing you to quickly identify trends and changes in performance.


# Statistics

The Statistics section provides a detailed view of how age verification is performing across your sites.

It helps you analyze traffic, monitor verification activity, and identify trends or potential issues.

The page is divided into two main areas:

* **Graph Data panel (top)**\
  Visual charts showing key metrics such as Sessions, Checks, Accesses, and Cost.
* **Table Data panel (bottom)**\
  A detailed breakdown of the same data by selected dimensions.

By default, statistics are shown for the last 7 days, but this can be adjusted using the date selector.

## <mark style="color:$primary;">Dimensions Available</mark>

Statistics can be analyzed across multiple dimensions, including:

* **Dates:** Year, Month, Week, Day, Hour
* **Sites:** Individual websites configured in your account
* **Countries:** Based on user IP address
* **Regions:** Based on user IP address
* **Operating Systems:** OS used by the end user
* **Browsers:** End-user browsers
* **Device Types:** Desktop, Mobile, etc.

## <mark style="color:$primary;">Filtering and Analysis</mark>

You can refine your data by applying multiple filters at the same time.

To apply filters:

1. Click + **ADD FILTER** at the top of the Statistics page.
2. Select a dimension (e.g. Site, Country, Browser).
3. Choose one or more values.
4. Click **APPLY**.

![Statistics Filters](https://content.gitbook.com/content/1v2DbmntPqhCff92tEVb/blobs/3uBacRTbpWlCQjGTUIXu/image)

Filter logic:

* Multiple values within the same dimension use **OR** logic.
* Filters across different dimensions use **AND** logic.

This allows you to:

* Compare performance across sites or countries.
* Analyze pass rates by device type.
* Review cost trends over time.

Filters can be reset at any time using **RESET FILTERS**.

## <mark style="color:$primary;">Metrics Available</mark>

The Statistics section supports the following metrics:

* **Sessions:** Number of visits to the verification page
* **Checks:** A Check is counted each time a verification method is started, including failed or abandoned attempts.

  A Check is also counted when:

  * a returning user logs in with AgeGO Log In (email, Google or passkey);
  * a user is recognised through Cross-Site Verification.

  Returning users recognised automatically through an active session or the Remember me option (including `ag_remember_me` in S2S) do not generate a Check.
* **Check Rate:** Checks / Clicks (percentage)
* **Accesses:** Total successful accesses after verification
* **Access Rate (Sessions):** Accesses / Sessions (percentage)
* **Cost:** AgeGO usage cost, in EUR.

## <mark style="color:$primary;">Exporting Data</mark>

You can download your statistics in CSV format:

* **Download Visible Data:** Exports only the columns currently shown
* **Download All Data:** Exports the full dataset

This allows you to perform deeper analysis externally if needed.


# My Sites

The My Sites section is where you manage the websites or apps that use AgeGO.

Each Site represents a single property where age verification is implemented.

## <mark style="color:$primary;">Creating a Site</mark>

To start using AgeGO, you must create at least one Site.

1. Go to My Sites.
2. Click **New Site**.
3. Fill in the required fields.

Site fields:

* **Name:** Internal name for the site.
* **Website URL:** Domain where AgeGO will run.
* **Callback URL:** URL called after verification completes.
* **Site Status:** Current operational status.

Site statuses:

* **Active:** Site is live and AgeGO is running.
* **Inactive:** Site is paused or disabled.
* **Archived:** Site permanently deactivated and hidden from active lists.

After creating a site, it becomes active immediately and AgeGO is ready to run.

![My Sites](https://1868684549-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1v2DbmntPqhCff92tEVb%2Fuploads%2FhfW1oxTOn0RjNTWzcES5%2FScreenshot%20blurred.png?alt=media\&token=0539745f-e8db-4142-bbf4-c7969051c7d3)

## <mark style="color:$primary;">Modal Close (X) toggle</mark>

{% hint style="warning" %}
This only applies to sites using the overlay (modal) integration, and only to sites that manage their own SFW/NSFW content split.
{% endhint %}

On the Create Site and Edit Site pages, under Site Status, you'll find a toggle labelled Modal Close (X).

* Off by default for every site, including existing sites.
* Turning it on adds a close (X) button to the age-verification screen on your site's overlay integration, allowing users to return to your unrestricted (SFW) content without verifying.
* This only applies to sites using the modal (overlay) integration. If your site uses S2S, enabling the toggle has no visible effect, the close button is never shown in the S2S flow.

#### **Turning it on**

When you switch the toggle on, a confirmation pop-up appears. You'll need to:

1. Read the warning, which explains that this feature is only suitable for sites with a content tier that's legally accessible without age verification, and that you're responsible for ensuring dismissed users only see that SFW content, in every jurisdiction where your users are located.
2. Tick a checkbox confirming you've read and accept the updated [Terms & Conditions](https://www.agego.com/terms-conditions-for-agego-business-customers) and meet the requirements to enable the feature.
3. Click Continue (only enabled once the checkbox is ticked) and save the site via Update/Create.

If you cancel the pop-up or navigate away without saving, the toggle stays off and nothing is recorded.

<div align="center"><figure><img src="https://1868684549-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1v2DbmntPqhCff92tEVb%2Fuploads%2FxNJ5RQ8WwqxfymMjDl7w%2Fenable-modal-close.gif?alt=media&amp;token=dd260f2a-9744-4712-9b80-d8ee4856ae70" alt=""><figcaption></figcaption></figure></div>

## <mark style="color:$primary;">Managing Sites</mark>

The Sites table shows all configured sites and includes:

* Site ID.
* Site name.
* Website URL.
* Status.

Available actions:

* **Edit:** Update site details.
* **View Statistics:** Open Statistics filtered for the selected site.
* **View HTML Tag:** Access integration options:
  * Basic Web.
  * Advanced Web.
  * Server-to-Server (S2S).

![](https://1868684549-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F1v2DbmntPqhCff92tEVb%2Fuploads%2FzzvwUxRlKyetncWxFz5j%2FScreenshot%20integration.png?alt=media\&token=c95f02ed-e402-4ccd-b653-22e28a1708a5)


# Payments

The **Payments** section explains how billing works and how to track usage and costs.

## <mark style="color:$primary;">Billing Model</mark>

AgeGO currently operates on a **post-payment model**.

This means:

1. You **do not need to add funds** in advance.
2. There is **no prepaid balance** or wallet.
3. You are **billed monthly**, based on your actual usage.

Usage is calculated according to the **number of age verification checks** performed during the billing period.

All amounts, including estimated costs and invoices, are in EUR.

## <mark style="color:$primary;">Tracking Usage and Costs</mark>

You can monitor your usage directly in the **Statistics** section of the AgeGO Dashboard.

In particular, you can review:

1. Number of checks.

   A Check is counted each time a verification method is started, including failed or abandoned attempts.

   A Check is also counted when:

   * a returning user logs in with AgeGO Log In (email, Google or passkey);
   * a user is recognised through Cross-Site Verification.
2. Estimated cost.
3. Usage over time

## <mark style="color:$primary;">Invoices</mark>

Invoices are issued **monthly**, based on your actual usage during the billing period.

To avoid invoicing issues, please make sure that:

1. Your **company or individual billing details** are correct.
2. Your **contact email** is up to date.

To add or update your billing details, open the user menu at the top right of the Dashboard and select **Profile**. Complete the Company/Individual details section (Tax Status, Company Name, VAT/TAX ID) and the Address details section (Country, Address, City, State / Province, Zip Code). Your contact email is under Account Contact.

No payment method needs to be added: invoices are issued monthly based on your usage.

## <mark style="color:$primary;">Need Help with Billing?</mark>

If you have any questions related to payments, billing, or invoices, please contact us at: <business@agego.com>


# Support

If you need help with your AgeGO integration or have questions about configuration, usage, or billing, our team is here to support you.

For any questions related to:

1. Technical integrations (Modal, S2S, callbacks, redirects).
2. Configuration or troubleshooting.
3. Dashboard usage or statistics.
4. Pricing, invoicing, or account setup.

Please contact us at: <business@agego.com>

To help us assist you more efficiently, please include:

1. The **email address used to register your AgeGO account.**
2. Your **Site ID.**
3. A brief description of the request or issue.
4. Any relevant screenshots or error messages.

**Business Terms & Conditions:** <https://www.agego.com/terms-conditions-for-agego-business-customers>


