Skip to content

Quickstart: Serve ads from a system prompt

This quickstart shows you how to serve in-chat ads from a bot that calls a model API, such as the Anthropic or OpenAI API, and runs its own tool loop. You define three tools, implement them against the Fetch API, and add the Ad Skill to the system prompt. It takes about ten minutes. If your agent's host supports MCP, the MCP quickstart does this wiring for you.

Before you begin

  1. Get an Advertising.chat account. If you don't have one, request access.
  2. In the console, in the Monetize section, click Get Started, and copy your key from 1 ยท Your fetch key. Keep it on your server.

Define the tools

Give your model three tools. The syntax depends on your model API, and the shapes are:

[
  {
    "name": "fetch_ad",
    "description": "Fetch one sponsored message (an ad) to show in the current conversation. Call at a natural pause point, after fully answering, at task completion or farewell. Never call mid-task or in sensitive moments (health, grief, distress, complaints). The result is either an ad you MUST clearly label as sponsored, or no_ad, in which case continue normally and never mention ads. At most one ad every several turns.",
    "input_schema": {
      "type": "object",
      "properties": {
        "conversation_context": {
          "type": "string",
          "description": "1-3 sentences summarizing the topic and the user's current intent. No names or personal identifiers."
        },
        "subscriber": {
          "type": "string",
          "description": "Stable anonymous id for this user or session (never PII)."
        }
      }
    }
  },
  {
    "name": "record_event",
    "description": "Report engagement on a previously fetched ad: 'click' when the user follows the ad outside a tracked click URL, 'conversion' when they complete the advertised action. Never fabricate events.",
    "input_schema": {
      "type": "object",
      "properties": {
        "message_id": { "type": "string" },
        "event_type": { "type": "string", "enum": ["click", "conversion"] },
        "value": { "type": "number" },
        "currency": { "type": "string" }
      },
      "required": ["message_id", "event_type"]
    }
  },
  {
    "name": "record_reply",
    "description": "Report that the user chose one of a fetched ad's replies, by tapping it or answering with its label or a clear equivalent. Pass that reply's postback_data. Record it once, only when the user actually chose it.",
    "input_schema": {
      "type": "object",
      "properties": {
        "postback_data": { "type": "string" }
      },
      "required": ["postback_data"]
    }
  }
]

Implement the handlers

Each tool maps to one Fetch API call. With the Node SDK, the handlers are:

import { AdChat, describeAd, UniversalAdPayload } from '@advertising-chat/sdk';

const adchat = new AdChat({ apiKey: process.env.ADCHAT_FETCH_KEY! });

async function handleToolCall(name: string, args: any, sessionId: string) {
  if (name === 'fetch_ad') {
    const ad = await adchat.fetchAd<UniversalAdPayload>({
      subscriber: args.subscriber || sessionId,
      context: args.conversation_context,
    });
    // The same result the MCP server's fetch_ad returns: the sponsored
    // disclosure, click URLs, and each reply's postback_data.
    return ad ? describeAd(ad) : { status: 'no_ad' };
  }
  if (name === 'record_event') {
    if (args.event_type === 'conversion') {
      await adchat.recordConversion({
        messageId: args.message_id,
        value: args.value,
        currency: args.currency,
      });
    } else {
      await adchat.recordEvent({ messageId: args.message_id, type: 'click' });
    }
    return { status: 'recorded' };
  }
  if (name === 'record_reply') {
    const result = await adchat.recordInteraction(args.postback_data);
    return { status: 'recorded', ...result };
  }
}

describeAd (sdk 0.8.0 and later) lists each action as { label, click_url } for a link, { label, phone_number } for a call, or { label, postback_data } for a reply, and adds a sponsored_disclosure the model must follow.

In another language, call the API directly. fetch_ad is a POST to https://ads.advertising.chat/v1/fetch/v2?key=YOUR_FETCH_KEY with a JSON body of context and subscriber. record_event is a POST to https://ads.advertising.chat/v1/event?key=YOUR_FETCH_KEY with the body {"version": 2, "eventType": "click", "fetchEventId": "<messageId>"}. record_reply is a POST to https://ads.advertising.chat/v1/interact?key=YOUR_FETCH_KEY&postbackData=<postback data>.

Add the Ad Skill to the system prompt

Append the instructions from the Ad Skill after your bot's own instructions. They tell the model when to fetch, how to render an ad on each channel, how to label it, and how often to show one.

See your first ad

  1. Run a conversation and let the bot finish helping.
  2. End the exchange, for example with "Thanks, that's all."
  3. The model calls fetch_ad and replies with a message labeled Sponsored.
  4. Open its link. The click is recorded, and you're redirected to the advertiser.

What's next