Skip to content

Capture SDK reference

Complete reference for the Shadow capture SDK — options, runtime API, and redaction rules.

The Shadow capture SDK records user sessions in the browser and streams them to the Shadow ingest API. It is framework-agnostic, works in any modern browser, and is safe to ship on every page.

Installation

Script tag

The canonical install. One line in the <head> of every page of your app:

<script async src="https://sdk.byshadow.ai/v1.js"
  data-site="YOUR_SITE_PUBLIC_KEY"></script>

The loader reads data-site at boot and fetches the rest of its configuration (origin allow-list, redaction rules, capture level) from the Shadow dashboard. No keys are embedded in your page.

Runtime API

Once loaded, the SDK installs a global window.__shadow (the __tutorialai legacy global is kept as an alias until a major version). The methods you’ll use in app code:

identify(jwt)

Associate the current session with an authenticated user so the widget and recorder UI can activate for tenant team members. Pass a short-lived JWT issued by your backend.

window.__shadow.identify(backendIssuedJwt);

The public passive capture runs without identify; you only need this if you want the widget / recorder to appear for signed-in team members.

waypoint(label, meta?)

Record a semantic waypoint in the current capture. Useful for marking meaningful moments ("project_created", "step_complete") the AI will weight during tutorial composition.

window.__shadow.waypoint('project_created', { plan: 'free' });

captureStep(opts?), startTour(opts?), stopTour()

Author-side APIs — these only do anything after identify() and are primarily called by the widget UI. See the widget docs for the full surface.

Runtime safety

  • All captures are batched and flushed via navigator.sendBeacon on pagehide.
  • Scheduled in requestIdleCallback — never blocks paint.
  • Sanitizes DOM before upload: inline event handlers and <script> contents are stripped.
  • Strict CSP compatible; the SDK never evaluates strings as code.

Privacy posture

  • Passive by default. No identify call, no author UI, no recording — just anonymous flow discovery.
  • PII redacted at capture. Elements matched by your redact.selectors, redact.attributes, or built-in patterns are masked in the browser before any network request.
  • Tenant-scoped. A site’s public key identifies only that tenant; requests are scoped at the API boundary.