Site SDK
A dependency-free script for your own site that lands agent hand-offs, injects JSON-LD and attributes conversions.
When an agent hands a customer to your own site, the site SDK closes the loop. It reads the hand-off token from the landing URL, classifies AI referrers, injects your JSON-LD projection, shows an accessible consent control and reports the conversion back, so it is attributed at the right tier. It collects no personal data.
Install
<script type="module">
import { init, injectJsonLd, identifyOrder } from "https://app.fondaq.ai/sdk/agora-site.js";
init({ merchant: "<your-slug>" });
injectJsonLd();
// on your confirmation page:
identifyOrder({ order_id: "<your reference>" });
</script>
A classic-script build with auto-initialisation is served at https://app.fondaq.ai/sdk/agora-site.legacy.js. The platform apps inject it for you. The full reference from the SDK package follows.
AGORA site SDK (agora-site.js)
Spec 17.3. Vanilla JavaScript, no dependencies, 3.4 KB gzipped (budget: 15 KB). Two builds, both committed:
| File | Format | Served by the demo server at |
|---|---|---|
dist/agora-site.js | ESM | GET /sdk/agora-site.js |
dist/agora-site.legacy.js | Classic script (IIFE, assigns window.agora, auto-inits from data-merchant) | GET /sdk/agora-site.legacy.js |
Rebuild with node build.mjs (fails if either file exceeds 15 KB gzipped). Source: src/agora-site.js.
What it does
| Function | Purpose | Collector event |
|---|---|---|
init({ merchant, endpoint?, origin?, autoLanding? = true }) | Sets the merchant slug and collector (default <origin>/sdk/collect), then captures the landing and referrer | — |
captureLanding(href?) | Reads ?h= / ?agora_h= (the handoff token nonce added by /h/:token), stores it in a first-party cookie agora_h (7 days) and localStorage; one event per nonce per session | handoff.landing.received { nonce, path, referrer_host } |
classifyReferrer(url, utm?) | Pure: chatgpt.com/chat.openai.com → chatgpt, gemini.google.com → gemini, perplexity.ai → perplexity, copilot.microsoft.com or bing.com/chat → copilot, claude.ai → claude, else utm_source mapping, else null | — |
captureReferrer() | Classifies document.referrer + utm_source, once per session | handoff.referrer.classified { surface, referrer_host, utm_source } |
injectJsonLd(objOrUrl?, id?) | Injects <script type="application/ld+json" id="agora-jsonld-<id>">; with no argument fetches the merchant's projection at /m/<slug>/jsonld. Idempotent per id; </ escaped | — |
identifyOrder({ order_id, total?, currency? }) | Sends the order with the stored nonce → tier 2 (token) attribution; with only a classified referrer → tier 3 | commerce.order.identified { order_id, nonce, surface, total, currency } |
mountConsent(el, { scopes, labels?, title?, onChange? }) | Accessible checkbox fieldset (labels bound to inputs, inline styles only, inherits the page font and colour) | lifecycle.consent.granted / lifecycle.consent.revoked { scope, scopes, nonce } |
send(type, attrs) | Low-level: navigator.sendBeacon (text/plain, no CORS preflight), fetch(keepalive) fallback | any |
Collector body (POST /sdk/collect, 204): { merchant, type, session_id, at, attrs, sdk }. No personal data is collected: the session id is a random per-tab id in sessionStorage, and order ids are the merchant's own references.
Usage
<!-- ESM -->
<script type="module">
import { init, identifyOrder, injectJsonLd, mountConsent } from "https://agora.oskar-d.com/sdk/agora-site.js";
init({ merchant: "dunes-electronics" });
injectJsonLd(); // the merchant's JSON-LD projection
mountConsent("#agora-consent", { scopes: ["agent_signals", "order_updates"] });
// on the order confirmation page:
identifyOrder({ order_id: "DEMO-1042", total: 2899.00, currency: "AED" });
</script>
<!-- Classic script, auto-init -->
<script src="https://agora.oskar-d.com/sdk/agora-site.legacy.js" data-merchant="dunes-electronics" defer></script>
<script>window.addEventListener("load", () => agora.identifyOrder({ order_id: "DEMO-1042" }));</script>
The platform apps in /apps/* inject the classic build (Shopify theme app embed, WooCommerce wp_enqueue_script, Magento layout XML, commercetools frontend snippet).
Browser support
Evergreen browsers (ES2018: async, arrow functions, URL, URLSearchParams). Storage access is wrapped so blocked cookies or storage only disable persistence, never throw.
Source: docs/portal/docs/site-sdk.md + sdk/js-site/README.md