VASTlint

VAST playback, tracking, and validation in React

Short answer: for validation only, use the published vastlint WASM package inside a React component. For the full runtime (loading a tag, resolving the wrapper chain, driving playback, and firing tracking), vastlint-react exposes headless hooks with validation built in.

vastlint-client matches the core runtime surface of vast-client-js (fetch, wrapper resolution, session state, tracking) and stays framework-agnostic; vastlint-react is a thin binding that turns it into hooks. The differentiator is that validation, source annotations, and issue mapping are first-class, not bolted on.

Status: preview

vastlint-react and vastlint-client are in active development and not yet published to npm. The validation path below, the vastlint package, is shipping today. Watch the roadmap for the hooks release.

Validate VAST in React today

This uses the published vastlint WASM package with no preview required.

import { useMemo } from 'react';
import { validate } from 'vastlint';

function VastReport({ xml }) {
  const result = useMemo(() => validate(xml), [xml]);

  if (result.summary.valid) return <p>Clean tag.</p>;

  return (
    <ul>
      {result.issues.map((issue) => (
        <li key={issue.id}>
          [{issue.severity}] {issue.id}: {issue.message}
        </li>
      ))}
    </ul>
  );
}

Headless hooks (preview)

import { useVastSession, useVastTracker, useVastPlayback } from 'vastlint-react';

function AdPlayer({ xml }) {
  const session = useVastSession({
    source: { kind: 'xml', xml },   // or { kind: 'url', url }
    autoLoad: true,
    autoValidate: true,
  });

  const tracker = useVastTracker({ session: session.session });
  const playback = useVastPlayback({ session: session.session });

  const validation = session.snapshot.validation?.summary;

  return (
    <div>
      {validation && !validation.valid && (
        <p>{validation.errors} VAST errors before playback</p>
      )}
      <button onClick={() => session.validate()}>Re-validate</button>
    </div>
  );
}

The hook surface:

  • useVastSession: load a source, resolve wrappers, expose a snapshot, and call validate() / fix() / resolve().
  • useVastPlayback and useVastPlaybackQueue: media selection and playback state for one ad or a pod.
  • useVastTracker: tracking dispatch with an event history and companion handling.
  • useVastAnnotations: map validation issues back onto the source XML for inline display.

Why validation belongs in the review UI

A broken VAST tag is a billed impression that renders nothing. The cheapest moment to catch it is before a human approves it, in the trafficking or QA screen where someone is already looking at the creative. Validating right there, in the browser, means the reviewer sees the exact errors and warnings on the tag they are about to ship, with no separate tool and no round trip to a validation service.

Because the validation engine is the same Rust/WASM core the bidder and ad server use, the issues a reviewer sees in the UI are the issues the pipeline enforces; there is no second, drifting implementation of “is this tag valid.” The hooks add the runtime on top so the same screen can also resolve the wrapper chain and play the ad back for a visual check.

Where it lands in an SSP or DSP's tooling

React is the front end of the ad-ops stack, so these hooks land in the human-facing tools an SSP, DSP, or ad server team runs alongside the delivery path:

  • Trafficking / creative review UI: validate and preview a tag as part of the approval step, blocking sign-off on hard errors.
  • Demand-partner QA dashboard: paste a partner's adm sample, see validation plus a live wrapper-chain resolution during onboarding.
  • Internal debugging console: a richer in-house version of the public tester, wired to your own fixtures and fetch logic.
  • Annotated diff view: use useVastAnnotations to map issues back onto the source XML, so a reviewer sees the problem on the exact line.

When not to use the React layer

If you only need a yes/no validation result and never touch playback, the vastlint package alone is enough. For a quick manual check use the web validator; for server-side validation see the Node.js guide.

Related reading