Skip to main content
Advanced patterns for creative preview integration including workflows, caching strategies, and implementation notes. For basic usage, see preview_creative.

Safe preview grids

Both HTML and URL output contain untrusted content. Use the empty-sandbox and caller-controlled CSP pattern for every preview, including previews from publisher-designated providers. HTML output still requires an iframe; a grid or a trusted transport does not permit host-DOM insertion. Shadow DOM provides CSS isolation, not a security boundary. This illustrative React component uses the previewSrcdoc helper from that pattern. The application supplies schema-validated HTML renders; URL renders require an enforceable policy for the cross-origin document, or a new request for HTML output. The JSX examples use application-provided clients, manifests, and review callbacks and are not standalone scripts.
test=false
The baseline blocks scripts and remote assets. If those restrictions prevent a complete review, obtain an inert render and show the limitation; do not add allow-scripts or allow-same-origin. Keep review controls in the host application. interactive_url does not authorize relaxing the preview policy; a separate interactive-testing integration needs its own isolation and credential controls.

Format showcase pages

Select only advertised preview capabilities and pass their explicit route IDs. These samples describe a renderer’s output, not creative approval or publisher acceptance. This application example assumes createExampleManifest builds the required assets for each declaration.
test=false
Render each successful item’s response.previews[].renders[] with PreviewFrame. Show each failed item’s errors[] as text instead of accessing a nonexistent success response. Split larger catalogs into batches of at most 50.

Campaign review grids

Request production quality explicitly, retain quality_used, and check each item before enabling a production-fidelity review action. This illustrative component assumes the application has already selected the applicable endpoint and route and retained the publisher delegation separately.
test=false
productionFidelity checks the response’s quality claim only. The component uses previewEntryIsFresh from the cache example below both when rendering controls and when handling a click. Check expiry again when recording a review decision; an open review page does not extend the artifact’s lifetime. Reviewers still verify that the displayed render is complete under the caller’s policy and inspect rendering origin and applicable publisher delegation. Neither this button nor a production-quality response grants seller approval or authorization to serve. Cache entries below retain the request, complete result, and discovery provenance for those checks.

Choosing output format

Use URL output when the caller can enforce restrictive CSP on the cross-origin preview document as well as an empty sandbox. A host page’s frame-src directive restricts frame locations, not the child document’s subresources. Do not assume a provider’s embedding recommendations enforce caller policy. Use HTML output when the caller constructs a srcdoc document with its own policy before provider markup. It is useful for grids and avoids a separate preview-page fetch, but still requires iframe isolation. Apply the same rules to server-rendered pages; do not interpolate preview markup into their HTML. Both paths may need a self-contained static rendering when scripts or remote media are blocked.

Caching review artifacts

A manifest-only key cannot identify a preview. The key must distinguish the endpoint and authenticated principal, exact renderer route, effective quality/output/template/catalog limit, all context and macro inputs, and the source/rendering/authority snapshots. Preserve the complete successful batch item, including its top-level quality_used; saving only result.response drops that evidence. The following executable helper defines application-local cache data, not new AdCP fields or SDK methods. The caller provides an existing client.preview_creative transport and schema-valid batch items. context records the exact endpoint and a non-secret tenant/principal scope matching that client, plus retained discovery evidence. sourceSnapshot binds the resolved source assets and any catalog/brand dependencies; renderingSnapshot identifies the known rendering configuration; authoritySnapshot records the applicable publisher delegation/presentation or an explicit undelegated state. These are local evidence identifiers, not self-granted authority. Do not put access tokens into keys. If any snapshot is unknown, the helper bypasses the cache. A mutable URL, creative ID, source revision, or manifest hash alone is insufficient. Invalidate on an observed renderer, source, or delegation change; an omitted preview expiry does not freeze those dependencies. This example requires an explicit route and quality so server defaults cannot silently change the cache identity. Batch defaults are materialized onto each item before the request and key are created.
test=true
A quality downgrade remains a successful result with a different quality_used. Keep it attached to the original requested quality; do not label it production or place it in a different request’s cache slot. Renderer metadata, output URLs and expiry, echoed inputs, and local discovery provenance survive cache hits unchanged. A cached generative preview reuses the same sample; bypass the cache to request a new sample. Cache lookup does not approve the artifact or establish historical delivery. On terminal transport errors, use the transport’s existing error handling; the example keeps allow_async at its default false.

Preview URL Storage

Preview URLs are review resources, not just transport conveniences. A buyer, browser, or MCPUI host may fetch a preview_url after the original preview_creative call returns, after a pod restart, or from a different pod than the one that created the render. For production agents, persist enough preview state to resolve every preview_url through its advertised lifetime:
  • If expires_at is present, keep the render available until that timestamp.
  • If expires_at is omitted, treat the URL as non-expiring at the protocol layer and keep it available until explicit out-of-band revocation or purge.
  • Use shared storage for multi-process or multi-pod deployments: database metadata plus object storage, a shared cache tier, or an authenticated preview route that can recover the render from durable session state.
  • Limit process-local Map or LRU storage to single-process demos, local development, or URLs whose advertised lifetime is shorter than the process lifetime you can actually guarantee.

Error handling

Check the batch envelope before reading item data, and check each item’s success before reading response. Batch failures use errors[], not a singular error. This illustrative application code assumes a connected client and prepared requests.
test=false

Migration from Single to Batch

Before (Sequential):
After (Batch):

Use Case Patterns

Device Variants

Geographic Variants

Privacy Compliance Testing

AI Content Variants

Implementation Notes

For Creative Agents

Required:
  1. Return complete HTML pages from preview_url
  2. Render every preview format the endpoint advertises, within the caller’s isolation policy
  3. Echo input parameters in response
  4. Validate manifest before rendering
  5. Apply macro values (or use defaults)
  6. Back preview URLs with storage that survives load balancing and restarts for the URL’s advertised lifetime
  7. Produce content compatible with the caller’s empty sandbox and restrictive CSP; do not ask consumers to enable scripts or same-origin access
  8. Set reasonable expiration (24-48 hours) for previews that should not be retained indefinitely
Optional enhancements:
  • Include render dimensions and renderer audit metadata when available
  • Provide embedding metadata (sandbox policy, CSP)
  • Support responsive design
  • Include accessibility features

For Buyers

  1. Render only in an empty-sandbox iframe with caller-enforced CSP; use the HTML srcdoc path when URL policy cannot be enforced
  2. Use inputs array for specific scenarios
  3. Check input field to confirm macros applied
  4. Share review artifacts with their quality, rendering origin, delegation provenance, and expiry
  5. Treat interactive_url as a separate untrusted testing surface; it never grants preview sandbox permissions

For Publishers

  1. Return consistent HTML from preview URLs
  2. Implement responsive preview pages
  3. For legacy named formats, document the coarse universal set via supported_macros; for canonical delivery paths, publish exact macro_resolution_capabilities on the selected format option
  4. Clarify preview vs production differences
  5. Consider providing interactive_url for testing