01Install the widget
Each store you add gets a public key. Paste the snippet once, high in the storefront's <head>, or add it as a custom HTML tag in your tag manager. It loads asynchronously and never blocks the page.
<script>(function(d,k){var s=d.createElement('script');s.async=true;s.src='https://airopopups.com/widget/w.js?k='+k+'&v=v1';d.head.appendChild(s);})(document,'YOUR_PUBLIC_KEY');</script>
The dashboard shows this snippet with your key already filled in. It works on any platform that lets you add a script: Shopify, WooCommerce, BigCommerce, WordPress, Magento, Webflow, Squarespace, Wix, PrestaShop, Shopware and headless storefronts.
02Verify your domain
Verifying confirms that you control the store's domain. Once the snippet is installed, press Verify on the store in the dashboard. If your platform can't run the snippet on the home page yet, add the verification tag from the dashboard to the <head> instead:
<meta name="airo-site-verification" content="YOUR_VERIFICATION_TOKEN">
03Cart and customer context
Targeting rules such as “cart over $40” or “logged-in customers only” read from two optional globals. Set them before the snippet runs, or update them as the cart changes:
window.airoCart = { value: 64.50, itemCount: 3 };
window.airoVisitor = { loggedIn: true, email: 'buyer@example.com' };
When a customer signs in after the page has loaded, call identify. The widget remembers them locally and re-checks which campaigns should still show, so someone who already subscribed is not asked again:
window.airo.identify('buyer@example.com', '+15551234567');
04Track conversions
On the order confirmation page, report the purchase so revenue is attributed to the campaign that earned it. A conversion also lifts “show once ever” caps for that visitor.
window.airo.track('conversion', { value: 49.99 });
If your confirmation page can't run scripts, report orders from your server instead (next section).
05Report orders from your server
This is the only endpoint that needs a secret, because it writes revenue. Generate an order secret under Settings → Developer; it is shown once and stored as a one-way hash. Send it as a bearer token, or in an X-Site-Secret header if your platform reserves Authorization. Never put it in the URL or in storefront HTML.
curl -X POST "https://airopopups.com/api/v1/widget/orders?k=YOUR_PUBLIC_KEY" \
-H "Authorization: Bearer YOUR_ORDER_SECRET" \
-H "Content-Type: application/json" \
-d '{"order_id":"1001","email":"buyer@example.com","value":89.90,"currency":"USD"}'
| Field | Required | Notes |
|---|---|---|
order_id | Yes | Your order reference, up to 255 characters. |
email | No | Links the order to a subscriber for attribution. |
value | No | Order total, 0 to 1,000,000. |
currency | No | Three-letter ISO code, e.g. USD. |
occurred_at | No | ISO 8601 date. Defaults to when we receive it. |
Reports are idempotent: sending the same order_id again is safe and is not counted twice. Responses: 201 with {"ok":true,"id":…} when recorded; 401 for a missing or wrong secret; 422 when a field fails validation; 429 when rate limited. A store that is over its plan's quota answers {"ok":true,"frozen":true} and records nothing.
06Receive subscribers by webhook
Klaviyo, Mailchimp and Brevo have native connections. For anything else, connect a Custom webhook under Integrations. We POST JSON to your URL for every new subscriber.
- The URL must be
https://on a public host. Private and internal addresses are refused, checked on every send. - If you set a secret, it is sent unchanged in the
X-Airo-Signatureheader. Compare it in constant time and reject anything that doesn't match. - Connecting sends a
{"type":"ping","subscriber":null}request; answer it with any 2xx. - A non-2xx answer or a timeout is retried with backoff, a limited number of times.
POST /your/endpoint
Content-Type: application/json
X-Airo-Signature: YOUR_WEBHOOK_SECRET
{
"type": "subscriber.created",
"site": "01JD3S8Q0Z8M7X2C4V6B9N1K3P",
"subscriber": {
"email": "buyer@example.com",
"phone": "+15551234567",
"attributes": { "quiz_answer": "Houseplants" },
"createdAt": "2026-10-14T09:21:07+00:00"
}
}
07Keys and rotation
- Public key: identifies the store to the widget. It is meant to be in your HTML. If you want a fresh one, rotate it and update the snippet; the old key stops working immediately.
- Order secret: authenticates server-to-server order reports. Generating a new one replaces the old one at once, so update your server first.
- Webhook secret: one you choose when connecting the webhook. Change it by reconnecting.
08Limits
Widget traffic is rate limited per visitor and per store to keep one noisy page from affecting anyone else. Normal storefront traffic never comes near the limits; a 429 means retry later. Plan limits on monthly visitors and stores are listed on the pricing section.