AnswerLine Start free

, Advertising · ChatGPT

Ads in ChatGPT answers: how they work and the ads[] fields

ChatGPT answers now carry advertising. OpenAI began testing ads in ChatGPT in the US on February 9, 2026, for logged-in adult users on the Free and Go tiers, with Plus, Pro, Business, Enterprise and Education tiers excluded; it later announced pilots in Canada, Australia and New Zealand (update of March 26, 2026) and plans for the United Kingdom, Mexico, Brazil, Japan and South Korea (update of May 7, 2026) (OpenAI, “Testing ads in ChatGPT”, checked 2026-09-17). If you buy media or watch competitors, the ads attached to your category’s prompts are now worth monitoring. One limit first: result.ads[] exists in the API, but it comes back empty on the ChatGPT answers served today, so the steps below describe the field and the method, not data you can collect now. Below: requesting them with include.ads, what each field means, and turning the results into advertiser share-of-voice numbers.

What OpenAI says about how the ads work

The same OpenAI post, checked 2026-09-17, states that:

Two consequences for measurement. First, because matching uses conversation and account context, one answer shows a single serving decision, not what every user sees; measure frequencies over many runs. Second, an empty ads[] on a health prompt is expected and says nothing about competitor spend.

Definitions

The request

Add include.ads to a ChatGPT request. Synchronously:

curl -X POST https://api.answerline.dev/v1/monitor/chatgpt \
  -H "Authorization: Bearer $ANSWERLINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "prompt": "best project management tools for small agencies", "country": "US", "include": { "ads": true } }'

Or as an async task, which fits prompt sets:

{
  "taskType": "CHATGPT",
  "payload": {
    "prompt": "best project management tools for small agencies",
    "country": "US",
    "include": { "ads": true }
  },
  "idempotencyKey": "ads-pm-small-agencies-us-2026-09-18"
}

The response fields

When include.ads is true, result.ads is an array with one entry per served ad. On the ChatGPT answers served today it comes back empty; the shape below is the contract:

{
  "success": true,
  "result": {
    "text": "…",
    "sources": [ { "position": 1, "url": "…", "label": "…", "description": "…" } ],
    "ads": [
      {
        "brand": { "name": "…", "url": "…", "favicon": "…" },
        "cards": [ { "title": "…", "body": "…", "url": "…", "image": "…" } ],
        "visibility": "allowed",
        "adsResponseIndex": 0,
        "rendered": true
      }
    ]
  }
}
Field Meaning
brand.name, brand.url the advertiser; brand.favicon is optional
cards[] the ad’s carousel cards, each with title, body, url and optional image
visibility OpenAI’s serving status: allowed means the ad was eligible to serve; hidden means OpenAI filtered it, for example by an integrity check
adsResponseIndex the ad’s slot in OpenAI’s served ad response; served order, not what was shown
rendered true if the ad was shown as a visible card; ads with rendered: false were served but not displayed

Use rendered for exposure. Do not infer exposure from adsResponseIndex 0: the index reflects served order only.

Served-but-not-rendered entries show which advertisers were in contention for the prompt even when another brand’s card was displayed, which is useful for competitive intelligence as long as you label it as “served”, not “seen”.

An ad-tracking run

1. Build the prompt set

Take the commercial prompts from your organic prompt set: category (“best X for Y”), comparison (“X vs Y”) and purchase-intent (“where to buy X”) questions. Informational and sensitive prompts rarely matter for ads. Designing a prompt set covers the rest.

2. Choose markets deliberately

Run the markets where you advertise or plan to. ChatGPT answers from 213 countries, including pilot markets such as the US, Canada, Australia, the United Kingdom, Brazil and Japan. Do not read an empty result as “nobody advertises here”: ads[] comes back empty on the ChatGPT answers served today in every market.

3. Submit and collect

import collections
import datetime as dt
import os
import time
import requests

API = "https://api.answerline.dev"
HEADERS = {"Authorization": f"Bearer {os.environ['ANSWERLINE_API_KEY']}"}
PROMPTS = {
    "pm-small-agencies": "best project management tools for small agencies",
    "pm-vs": "Asana vs Monday for a marketing team",
    "time-tracking": "which time tracking app should a consultancy buy",
}
MARKETS = ["US", "CA", "AU"]
day = dt.date.today().isoformat()

tasks = [
    {
        "taskType": "CHATGPT",
        "payload": {"prompt": p, "country": c, "include": {"ads": True}},
        "idempotencyKey": f"ads-{pid}-{c.lower()}-{day}",
    }
    for pid, p in PROMPTS.items()
    for c in MARKETS
]
batch = requests.post(f"{API}/v1/async/task/batch", json=tasks, headers=HEADERS, timeout=60)
batch.raise_for_status()
ids = [r["task"]["id"] for r in batch.json()["results"] if r["success"]]

results = {}
while len(results) < len(ids):
    for tid in ids:
        if tid in results:
            continue
        data = requests.get(f"{API}/v1/async/task/{tid}", headers=HEADERS, timeout=30).json()
        if data["task"]["status"] in ("COMPLETED", "FAILED"):
            results[tid] = data
    time.sleep(10)

For recurring runs, replace polling with a webhook on each task (webhooks).

4. Aggregate served and rendered ads

served = collections.Counter()
rendered = collections.Counter()
creatives = collections.defaultdict(set)
answers = 0

for data in results.values():
    if data["task"]["status"] != "COMPLETED":
        continue
    answers += 1
    for ad in data["response"]["result"].get("ads", []):
        name = ad["brand"]["name"]
        served[name] += 1
        if ad["rendered"]:
            rendered[name] += 1
        for card in ad["cards"]:
            creatives[name].add(card["title"])

total_rendered = sum(rendered.values())
for name, count in served.most_common():
    print(
        f"{name:30} served {count / answers:6.1%} "
        f"rendered {rendered[name] / answers:6.1%} "
        f"paid SoV {rendered[name] / total_rendered if total_rendered else 0:6.1%} "
        f"creatives {len(creatives[name])}"
    )

Store the raw task JSON with the date, prompt id and market. Card titles and bodies over time are a record of competitors’ messaging tests.

Worked example

These numbers are invented to show the calculation. 30 prompts in one market give 30 completed answers. Brand A is served in 12 and rendered in 7; brand B is served in 9 and rendered in 5; no other brand is rendered. Brand A’s served presence rate is 12 / 30 = 40%, its rendered presence rate 7 / 30 = 23.3%, and its paid share of voice 7 / (7 + 5) = 58.3%. Brand B is served in 9 answers but rendered in only 5, so in 4 answers it was in contention and another ad (or none) was displayed.

What to do with the data

For the organic side of the same answers, see how AI engines choose citations and measuring brand mentions.

Ads on Google surfaces

Google’s surfaces carry ads too, and the Google endpoints return ads with their own shapes.

Surface Field Key subfields
Google Search result.ads[] position, blockPosition (top, bottom, middle, rhs), type (RESULT, SHOPPING_CARD), title, url, displayedUrl, domain, description, page, sitelinks[], and for shopping cards price, oldPrice, store, category, imageUrl
Google AI Overview result.aioverview.ads[] position, title, url, type (TEXT or SHOPPING); domain and description on TEXT, price and store on SHOPPING
Google AI Mode result.ads an object with title and ads[] (title, url, position, price, store, rating, reviews)

AI Overview ads need include.aioverview on the Google request (+$0.00071 on the $0.00103 Google Search task). A combined view (ChatGPT ads, Google text ads and AI Overview ads for the same keyword) shows where a competitor concentrates spend. See Google AI Overviews monitoring, SERP feature tracking and the Google Search engine page.

Cost

A ChatGPT task is $0.0006 at the Starter tier, and include.ads and include.shopping are free. So a task with ads, or with ads and shopping, is $0.0006.

Run Tasks Cost
30 prompts x 1 market, tasks with ads 30 $0.018
90 prompts x 1 market, tasks with ads and shopping 90 $0.054

New accounts get 100 free requests on any engine, ChatGPT included, enough for 100 tasks with ads; after that you top up your balance. See pricing for tier prices and cost planning for budgeting.

Pitfalls

Field definitions are in the API reference; engine details on the ChatGPT engine page.

Questions

Does ChatGPT show ads?

Yes. OpenAI began testing ads in ChatGPT in the US on February 9, 2026, for logged-in adults on the Free and Go tiers, and later announced pilots in more countries. Ads are labeled as sponsored and shown separately from the answer.

How do I get ChatGPT ads from the API?

Set include.ads to true on a ChatGPT request or CHATGPT task. The result then carries ads[], one entry per served ad, with brand, cards, visibility, adsResponseIndex and rendered. On the ChatGPT answers served today the array comes back empty.

What is the difference between a served ad and a rendered ad?

ChatGPT can serve several candidate ads for one response but displays at most one. Every served ad appears in ads[]; the one actually shown as a card has rendered set to true.

How much does ad tracking cost?

include.ads is free, so a ChatGPT request with it costs the base $0.0006 at the Starter tier. Shopping and rawResponse are free too.

Why is ads[] empty for my prompt?

Because ads[] comes back empty on the ChatGPT answers the API serves today, whatever the prompt and market. Separately, OpenAI says ads are not eligible near sensitive or regulated topics such as health, mental health or politics, and its ad pilots run in specific countries.

Can I track Google ads the same way?

Google Search responses carry their own ads[] with position, blockPosition, type, title, url, domain and description, and AI Overview ads appear under aioverview.ads[]. The field shapes differ from ChatGPT's, so parse them separately.

Try it on your own prompts

100 free requests on any engine, no card. One POST returns the answer, sources and citations as JSON.

Keep reading