Prism Publication

For publishers wiring a bot

How do you attach Prism to your bot?

Your bot runs on whatever backend you already use. There is no Prism-hosted secret key, and nothing to install on your side beyond one function call. After the bot finishes a reply, call displayAd from your server. It reads a public catalog file hosted on this site. The chat widget only draws HTML you already trust.

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 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] if you are putting this on a live bot. Advertisers submit creatives on ad submission. Do not treat the module URL as a page to send a media buyer.

Does my bot need to run on Cloudflare Pages?

No. displayAd runs on your own server, on whatever backend you already use: Node, a Worker, anything that can make an HTTPS request. It just reads a static catalog file hosted on this Pages site. There is no key server and no database on this host. Call it after the assistant reply. Do not load the client in the chat widget. The file is /sdk/catalog.json.

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. The widget never calls Pages for a secret. The catalog is a public JSON file on this site.

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

const card = await displayAd({
  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. The catalog is /sdk/catalog.json. Open those links only if you are wiring an integration. Omit gam and the call stays on the Pages catalog. sdk/gamClient.js is the GAM fan-out leg.

How does Google Ad Manager fan-out work?

Google Ad Manager is available. Both legs fire on the server in parallel. Neither GAM credential 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 the Pages catalog both return a card, the GAM card is the one you render. Track helpers on the Pages path return ok with no remote POST. 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