Prism Publication

For publishers wiring a bot

How do you attach Prism without putting a key in the browser?

Keep the key on your server. After the bot finishes a reply, ask Prism for a card. The chat widget only draws HTML you already trust. This page is the human guide. The JavaScript module is a file your server imports. It is not a landing page.

By Daniel Rosenthal. Published . Last updated .

What does your server do?

Call displayAd from Node or a Worker. Never bundle it into the chat widget. Pass botId, format: "card", and the user question as topic. If you get a card, render title, description, destination URL, and a sponsored label that uses the advertiser's brand or product name. If you get nothing, send the assistant reply alone. Matching must finish under 120 milliseconds or you also send the reply alone. Google Ad Manager is available as a second demand leg on that same call.

Email [email protected] for a key. Advertisers submit creatives on ad submission. Do not paste the key into frontend code, and do not treat the module URL as a page to send a media buyer.

What does a fill look like in code?

Import the client on the server, wait for the assistant, then decide card or silence. Copy this shape. Put your key in an environment variable. The widget never sees it.

import { displayAd } from "./prismClient.js";

const card = await displayAd({
  apiKey: process.env.PRISM_API_KEY,
  botId: "your-bot-id",
  topic: userQuestion,
  format: "card",
  gam: {
    fillUrl: process.env.GAM_FILL_URL,
    networkCode: process.env.GAM_NETWORK_CODE,
    adUnitCode: process.env.GAM_AD_UNIT_CODE,
  },
});

if (!card) {
  // send the assistant reply with no sponsored card
}

The module file lives at /sdk/prismClient.js for servers that import by URL. Open that link only if you are wiring an integration. It is source, not a product page. sdk/gamClient.js is the GAM fan-out leg. Omit gam and the call stays Prism-only.

How does Google Ad Manager fan-out work?

Google Ad Manager is available. Both legs fire on the server in parallel. Neither key belongs in the chat widget. Set fill URL, network code, and ad unit in environment variables or on the gam object. Each leg has 120 milliseconds. A miss or timeout on one leg is null, not a stall. If GAM and Prism both return a card, the GAM card is the one you render. Track Prism fills with trackImpression / trackClick. GAM fills stay on the GAM stack.

Do not load googletag in the transcript. Ad ops copy for buyers is on ad submission.

What floors should you quote internally?

Serve only when the question is close enough to the ad copy, finish matching in under 120 milliseconds, and label every card with the advertiser's brand. Cosine similarity 0.65 is how closeness is measured. Null means no card and no bill. Timeouts fail the same way.

Publisher matching floors
What you ship What we measure Floor If missed
Card only when the user is already asking about that product Cosine similarity of the question vs the creative 0.65 No card, no bill
The chat does not stall Match latency Under 120ms No card, no bill
The user can tell it is an ad from that brand Disclosure on the card Sponsored, plus advertiser brand or product name Creative does not run