Demo build. Every business shown is fictional, data is synthetic and partner integrations are simulated.What is real here

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:

FileFormatServed by the demo server at
dist/agora-site.jsESMGET /sdk/agora-site.js
dist/agora-site.legacy.jsClassic 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

FunctionPurposeCollector 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 sessionhandoff.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 sessionhandoff.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 3commerce.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) fallbackany

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