Skip to content
Docs/SDKs

Web (Browser)

Experimental source reference. Zero-dependency browser SDK with an auto-rendering banner API and a framework-agnostic client.

Experimental — verify runtime eligibility

Browser requests require an approved origin. The checked contract records a first-party CORS limitation; confirm your domain before live requests. Public package: Not verified. Source version: 1.0.0. See availability and capability evidence.
Package@theaimart/adx-web
LanguageTypeScript
DistributionSource only; public installation not verified
RequirementsAny modern browser (evergreen Chrome/Firefox/Safari/Edge).

Install

Source setup — accessible SDK checkout required

bash
cd packages/web
npm ci
npm run build

Usage

Auto-rendering banner

html
<div id="taim-ad-8b1f2c3d"></div>
<script type="module">
  import { TaimAds } from '@theaimart/adx-web';
  TaimAds.init({ apiKey: 'pk_your_publisher_key' });
  TaimAds.createBanner({
    slotId: '8b1f2c3d-....-uuid',   // container defaults to #taim-ad-<slotId>
    lazy: true,                      // request only when near viewport
    refresh: 60,                     // auto-refresh seconds (clamped to >=30)
    onLoad: (ad) => console.log('filled', ad.source),
    onError: (err) => console.log('no fill', err.message),
  });
</script>

Framework-agnostic client (React/Vue/custom)

ts
import { AdxWebClient, AdKind } from '@theaimart/adx-web';

const client = new AdxWebClient({ apiKey: 'pk_your_publisher_key' });
const ad = await client.requestAd({ slotId: '8b1f-uuid', pageUrl: location.href });
if (ad.filled) {
  // render ad.creative yourself (img+anchor, or sandboxed iframe for ad.kind === AdKind.Html)
  // After rendering and measuring ≥50% visibility for ≥1s:
  // if (ad.isTrackable) await client.reportViewable(ad.impId!);
}
CORS origin note: the backend currently allows cross-origin serving only from adx.theaimart.co/theaimart.co. Serving on a publisher domain requires approved-origin CORS support. Confirm domain eligibility with support before live requests; an ad request can have billing side effects even if the browser rejects the response. Never reflect arbitrary origins with credentials. Native mobile/server SDKs are unaffected.
Browser requests require an approved origin. The checked contract records a first-party CORS limitation; confirm your domain before live requests.

Production hardening

  • SQL-filter-safe encoding of pageUrl/keywords/consent so real URLs never trip the backend WAF.
  • Header-less simple GET with credentials: 'include' — no custom header means no CORS preflight; the _an_id identity cookie flows automatically.
  • Fail-closed: any error/non-200 → no-fill; ads never throw into your page.
  • Beacons use navigator.sendBeacon (survives teardown), falling back to keepalive fetch.

These behaviors come directly from the wire contract — see User-Agent rules and WAF-safe encoding for why they matter. Not getting fills? See Troubleshooting.

API

MemberNotes
TaimAds.init({ apiKey, baseUrl? })Configure the global auto-render controller once.
TaimAds.createBanner({ slotId, container?, lazy?, refresh?, onLoad?, onError? })Render a banner into a container (defaults to #taim-ad-<slotId>).
new AdxWebClient({ apiKey, baseUrl? })Framework-agnostic client for custom rendering.
client.requestAd({ slotId?, slotName?, pageUrl?, pageKeywords?, usPrivacy?, euconsentV2? })Request an ad decision — returns a normalized Ad.
client.reportViewable(impId)Fire the viewability beacon.
isSafeHttpUrl(url)The same http(s)-only scheme check the SDK uses internally before turning a click_url into a link — exported for custom renderers.

The normalized Ad model

AdKind (Image/Html/NoFill), AdSource (Internal/OpenRtb/House), plus the shared filled/impId/creative/auction/isTrackable fields common to every SDK.

Advanced

Beyond the core v1 contract, the source contains additional client-side capabilities; validate their runtime behavior before production use:

Mediation (waterfall + bidding across networks)

MediationController fetches a publisher's mediation chain from the public config endpoint and runs it: taimads first-party demand and any bidding adapters compete in parallel on price; if nothing bids, waterfall adapters are called in priority order until one fills. External networks (AdMob, Meta, …) ship their own proprietary SDKs the package can't bundle, so integrators register an AdapterFn per network that wraps that network's SDK — taimads itself is always the built-in bidding entry, no adapter needed.

VAST video playback

parseVast understands the VAST 2.0/4.0 documents the ad server emits (a single InLine linear ad) — it is deliberately not a general-purpose VAST parser. playVastAd wires the result onto an HTML5 <video> element with IAB-correct beaconing (impression fires once on first play).

On-device persona (privacy-preserving contextual targeting)

recordTopic/topTopics count interest topics in the user's own localStorage — nothing is uploaded. At request time, the top topics ride the serve call as plain contextual keywords: no identifier, no profile, server-side privacy and consent still require review. clearPersona lets the user wipe it entirely.

Ad inspector overlay

enableInspector() drops a floating debug panel listing every ad the page rendered — network, impression id, clearing price — with one-click links to the public nutrition label at /why/{imp_id} where a receipt may be available if enabled. Review the exposed information before enabling the inspector in production behind ?adx_debug=1.

Build & test

bash
cd packages/web
npm install
npm test           # node --test (core + encoding logic)
npm run typecheck  # tsc --noEmit
npm run build      # tsc -> dist (ESM + types)
npm run build:cdn  # esbuild -> dist/taimads.global.js (IIFE for <script>)