Quickstart: Serve ads with the Node SDK¶
This quickstart shows you how to serve in-chat ads from
your own Node.js code with @advertising-chat/sdk, a typed client for the
Fetch API. Your code decides where ads appear. It takes about five minutes.
To let an agent decide instead, see the MCP quickstart.
Before you begin¶
- Get an Advertising.chat account. If you don't have one, request access.
- In the console, in the Monetize section, click Get Started, and copy your key from 1 ยท Your fetch key. Keep it on your server.
- Install Node.js 18 or later.
Install the SDK¶
The package includes TypeScript types and has no runtime dependencies.
Fetch an ad¶
import { AdChat, UniversalAdPayload } from '@advertising-chat/sdk';
const adchat = new AdChat({ apiKey: process.env.ADCHAT_FETCH_KEY! });
const ad = await adchat.fetchAd<UniversalAdPayload>({
subscriber: sessionId, // anonymous id, used for frequency caps
context: [
{ role: 'user', text: 'What is a good gift for a coffee lover?' },
{ role: 'assistant', text: 'A quality burr grinder is a great pick.' },
],
});
if (!ad) {
// No ad fits this moment. Continue without one.
return;
}
console.log(ad.messageId); // use for event reporting
console.log(ad.payload.title); // "Acme Coffee Grinder"
console.log(ad.payload.actions); // [{ text: 'Shop now', navigate: { url: 'https://...' } }]
context is either a string summary or an array of { role, text } turns.
It selects this ad and is not kept as history. fetchAd resolves to null
when no ad fits.
Render the ad for your channel¶
The default format is a channel-neutral card. Two helpers map it to common surfaces and add the Sponsored disclosure:
import { renderWebchat, renderWhatsApp } from '@advertising-chat/sdk';
const web = renderWebchat(ad.payload);
// { text, imageUrl, buttons: [{ label, url, postbackData, id }], disclosure: 'Sponsored' }
const wa = renderWhatsApp(ad.payload);
// A WhatsApp Cloud API message object with the footer "Sponsored": a link
// button, or up to three reply buttons when the ad has replies.
// Send it with your recipient: { ...wa, to }
To receive a channel's native message from the server instead, pass
format to fetchAd with one of the values in
Render formats, such as sms or
rcs-google, and forward ad.payload to your gateway.
Track clicks and conversions¶
The action URLs in the payload are click-tracking links. Present them unchanged, and each tap is recorded before the person reaches the advertiser.
Report other engagement explicitly:
// The person acted on the ad outside a tracked link:
await adchat.recordEvent({ messageId: ad.messageId, type: 'click' });
// The person completed the advertised action:
await adchat.recordConversion({
messageId: ad.messageId,
name: 'purchase',
value: 19.99,
currency: 'USD',
});
Both methods resolve with no value on success and throw an AdChatApiError,
with status and reason, on failure.
Report reply taps¶
Some ads offer replies, such as "Add it" and "No thanks", instead of a link.
A tap comes back to your code as the person's next message, carrying the
reply's postback data. Pass it to recordInteraction:
import { messengerPostbackData, whatsAppPostbackData } from '@advertising-chat/sdk';
// Messenger webhook, for each `messaging` event:
const fromMessenger = messengerPostbackData(event);
// WhatsApp webhook, for each message in `value.messages`:
const fromWhatsApp = whatsAppPostbackData(message);
// Webchat: the tapped button's `postbackData` from renderWebchat.
const postbackData = fromMessenger ?? fromWhatsApp;
if (postbackData) {
await adchat.recordInteraction(postbackData);
}
On RCS, pass suggestionResponse.postbackData, after checking it with
isAdPostbackData. A reply that accepts or declines an offer records the
person's answer, which the advertiser's rules can use. See
Responses to an offer.
What's next¶
- Read about in-chat ads and the duties of hosting them.
- Let an agent decide when to place ads with the MCP quickstart.
- Read the event types in the Events API reference.