Intentara / Docs
Dashboard

JavaScript SDK

A lightweight vanilla JavaScript SDK with Shadow DOM isolation, session tracking, and auto-fill.

Installation

Add the script tag to your HTML page, ideally before your application code:

html
<script src="__BASE_URL__/sdk/intentara.js"></script>
No build step required The SDK is a single vanilla JS file with zero dependencies. It works in any browser environment without bundlers or transpilers.

Methods

intentara.init(config)

Initialize the SDK with your API key. Call this once before using any other method. Automatically generates an anonymous session ID for analytics (in-memory only — no cookies or localStorage).

ParameterTypeDescription
apiKey requiredstringYour Intentara public publisher key (starts with pub_).
baseUrl optionalstringOverride the API base URL. Defaults to __BASE_URL__. Use an HTTPS origin in production.
javascript
intentara.init({
  apiKey: 'pub_XXXX',
});

intentara.getAd(options)

Fetch the most relevant ad for a given conversation context. Returns a Promise<Ad | null>.

ParameterTypeDescription
context requiredstringThe conversation context text. Send the existing chat history plus the current user input so you can request the ad before the LLM response is ready.
signal optionalAbortSignalAn AbortSignal to cancel the request. Useful for SPA cleanup in useEffect or route changes.
javascript
const context = [...chatHistory, currentUserInput].join('\n');

const ad = await intentara.getAd({
  context,
});

if (ad) {
  console.log(ad.name);       // Creative name
  console.log(ad.text);       // Ad copy
  console.log(ad.targetUrl);  // Click-through URL
  console.log(ad.imageUrl);   // Optional image
}

With AbortController (for SPA cleanup):

javascript
const controller = new AbortController();

const ad = await intentara.getAd({
  context: 'running shoes for marathon training',
  signal: controller.signal,
});

// Cancel if needed (e.g., on route change)
controller.abort();

The returned ad object has this structure:

Ad Object
{
  id: string;               // Creative ID
  name: string;             // Creative name
  text: string | null;      // Ad copy text
  imageUrl: string | null;  // Ad image URL
  impressionUrl: string;    // Impression tracking pixel URL
  targetUrl: string;        // Click-through URL (with tracking)
  score: number;            // Relevance score
}

intentara.render(ad, element, options?)

Render an ad into a DOM element using Shadow DOM for style isolation. Impression tracking is handled automatically by loading ad.impressionUrl during rendering.

ParameterTypeDescription
ad requiredobjectThe ad object returned by getAd().
element requiredHTMLElementThe DOM element to render the ad into.
options.template optionalstring"card" (default) or "native". Card shows a full ad card with image, title, description, and CTA. Native renders a compact inline text link.
options.position optionalstring"inline" (default — replaces content), "suffix" (appends), or "prefix" (prepends).
javascript
// Card template (default) — full ad card
intentara.render(ad, document.querySelector('#ad-slot'));

// Native template — compact inline text link
intentara.render(ad, document.querySelector('#ad-slot'), {
  template: 'native',
});

// Suffix position — append after existing content
intentara.render(ad, document.querySelector('#chat-message'), {
  template: 'card',
  position: 'suffix',
});

intentara.process(options)

Auto-fill: scans the DOM for all [data-intentara-slot] elements, fetches one ad, and renders it into every slot. Each slot can specify its own template via data-intentara-template.

ParameterTypeDescription
context requiredstringThe conversation context for ad matching.
signal optionalAbortSignalAbortSignal to cancel the request and prevent rendering.
onFill optionalfunctionCalled with the ad object when an ad was successfully rendered.
onNoFill optionalfunctionCalled when no matching ad was found (or no slots exist).
onError optionalfunctionCalled with the error object if the request fails.
html
<!-- In your HTML -->
<div data-intentara-slot></div>
<div data-intentara-slot data-intentara-template="native"></div>
javascript
const context = [...chatHistory, currentUserInput].join('\n');

intentara.process({
  context,
  onFill: (ad) => console.log('Ad rendered:', ad.name),
  onNoFill: () => console.log('No matching ad'),
  onError: (err) => console.error('Ad error:', err),
});

Templates

Card (default)

A visually distinct ad card with optional image, an "Ad" label, and a "Learn more" call-to-action link.

text
┌──────────────────────────────────┐
│ [Image if available]             │
│ ─────────────────────────────    │
│ Ad                               │
│ Learn more →                     │
└──────────────────────────────────┘

Native

A compact inline text link that blends with surrounding content. No image, minimal footprint.


Shadow DOM

Every rendered ad is wrapped in a Shadow DOM boundary. This means:


CSS Variables (Theming)

Customize ad appearance from outside the Shadow DOM by setting CSS variables on the slot element or any ancestor:

css
[data-intentara-slot] {
  --intentara-bg: #ffffff;       /* Card background */
  --intentara-text: #1a1a1a;     /* Text color */
  --intentara-accent: #2563eb;   /* CTA link color */
  --intentara-border: #e5e7eb;   /* Border color */
  --intentara-radius: 8px;       /* Border radius */
}

Example — dark theme:

css
[data-intentara-slot] {
  --intentara-bg: #1e293b;
  --intentara-text: #f1f5f9;
  --intentara-accent: #60a5fa;
  --intentara-border: #334155;
  --intentara-radius: 12px;
}

Session Tracking

init() generates a random session ID (crypto.randomUUID()) that is sent as an x-session-id header with every API request. This enables:

The session ID is stored in-memory only — it resets on page reload and never touches cookies or localStorage. No cookie banner required.


Complete Example

html
<!DOCTYPE html>
<html>
<head>
  <title>My AI Chat</title>
  <script src="__BASE_URL__/sdk/intentara.js"></script>
  <style>
    /* Optional: customize ad appearance */
    [data-intentara-slot] {
      --intentara-bg: #f8fafc;
      --intentara-accent: #2563eb;
    }
  </style>
</head>
<body>
  <div id="chat"></div>

  <!-- Ad slots — auto-filled by process() -->
  <div data-intentara-slot></div>

  <script>
    intentara.init({ apiKey: 'pub_XXXX' });

    async function onUserSubmit(chatHistory, currentUserInput) {
      document.getElementById('chat').textContent = currentUserInput;
      const context = [...chatHistory, currentUserInput].join('\n');

      await intentara.process({
        context,
        onFill: (ad) => console.log('Showing:', ad.name),
      });
    }

    onUserSubmit(
      [
        'User: I need new running gear.',
        'Assistant: Are you training for road races or trail runs?'
      ],
      'User: Road races. I need shoes for marathon training.'
    );
  </script>
</body>
</html>