How OpenAI Serves Ads in ChatGPT: Selection, Guardrails, and Attribution
As of April 29, 2026, OpenAI is no longer merely “considering” ads. It is actively testing ads in ChatGPT. That matters because conversational advertising is not the same as search ads, social ads, or display ads. The selection surface is different, the trust constraints are tighter, and the attribution story is intentionally narrower.
If you want the short version, it is this:
- OpenAI says ads are separate from model answers
- ads are currently shown below the end of a response
- the selection starts with the current chat thread
- if a user allows personalization, OpenAI may also use past chats, memory, and ad interaction history
- advertisers do not get the user’s chat logs, memory, name, email, precise location, or IP address
- OpenAI has publicly described aggregated reporting such as views and clicks, not a fully exposed, user-level attribution stack
That is the public baseline. The more interesting question is how such a system likely works in production.
This article separates documented facts from technical inference so the architecture stays honest.
First: what OpenAI has publicly confirmed
OpenAI’s current public documentation says:
- ads are being tested in ChatGPT for Free and Go users
- Plus, Pro, Business, Enterprise, and Edu are ad-free
- ads appear below the answer, clearly labeled as sponsored
- ads do not influence the model’s answer
- ads do not appear in Temporary Chats
- ads are not eligible near sensitive or regulated topics, including health, mental health, and politics
- users under 18 are excluded when OpenAI knows or predicts they are under 18
- ad selection starts with the current chat thread
- if personalized ads are enabled, selection may also use past chats, memory, and ad interactions
- advertisers receive aggregated, non-identifying performance data such as views and clicks
There are also two important date markers:
- OpenAI says the U.S. ad test began on February 9, 2026
- on March 26, 2026, OpenAI said it was expanding pilots beyond the U.S. to Canada, Australia, and New Zealand
So if you still think “OpenAI does not serve ads,” that was true before February 9, 2026. It is not true now.
What makes conversational ad serving different
Traditional ad systems usually work from page context, search queries, audience segments, or feed behavior. ChatGPT adds a new input surface: a multi-turn conversation where intent develops over time.
That changes the stack.
A normal display ad request might look like this:
{
"page_url": "/best-running-shoes",
"slot": "sidebar_300x250",
"geo": "US",
"device": "mobile"
}
A conversational ad request has to look more like this:
{
"surface": "chatgpt_response_footer",
"conversation_id": "conv_8d9f",
"turn_id": "turn_42",
"market": "US",
"language": "en",
"plan": "free",
"temporary_chat": false,
"user_age_bucket": "18_plus",
"ad_personalization": true,
"signals": {
"current_thread_topics": ["meal planning", "grocery delivery", "budget dinner"],
"recent_ad_feedback": ["hide:luxury-travel"],
"memory_topics": ["vegetarian", "lives in chicago"],
"brand_safety_context": "safe"
}
}
The difference is not cosmetic. In a chat product, the ad system has to answer at least five questions before it can render anything:
- Is this user eligible to see ads at all?
- Is this conversation safe for ad placement?
- Is there enough intent or topic clarity in the current thread to retrieve relevant candidates?
- Should the system use only thread context, or also personalization signals?
- Can the ad be shown without confusing the user about what is the answer and what is the ad?
OpenAI’s public materials strongly suggest that this pipeline exists, even if they do not publish the internal implementation.
A plausible production architecture
Based on what OpenAI has documented, a minimal serving path probably looks something like this:
User message
-> Chat model generates response
-> Separate ad system receives conversation-safe context
-> Eligibility filter runs
-> Sensitive-topic / brand-safety filter runs
-> Candidate ads retrieved from approved inventory
-> Relevance ranking runs
-> Single sponsored unit selected
-> Ad rendered below response
-> Impression / click events logged in aggregate-safe analytics
That “separate ad system” detail matters. OpenAI explicitly says ads run on separate systems from the chat model and advertisers cannot shape or alter the response itself. So the likely product architecture is not “the model writes an answer with an ad inside it.” It is closer to “the response renderer composes an answer block and, if policy allows, appends a sponsored module underneath.”
In pseudo-TypeScript:
type AdEligibility = {
canShowAds: boolean;
reason?:
| "paid_plan"
| "temporary_chat"
| "minor_or_predicted_minor"
| "sensitive_context"
| "market_not_enabled"
| "no_relevant_inventory";
};
function maybeAttachAd(input: AdRequest, answer: ModelAnswer) {
const eligibility = evaluateEligibility(input);
if (!eligibility.canShowAds) {
return { answer, ad: null, eligibility };
}
const candidates = retrieveEligibleAds(input);
const ranked = rankByRelevance(input, candidates);
const ad = ranked[0] ?? null;
return {
answer,
ad,
eligibility,
placement: ad ? "below_response" : "none",
};
}
That is not OpenAI source code. It is the simplest architecture that fits the public product behavior.
How ads are selected during a conversation
This is the part most people actually care about.
OpenAI’s help documentation says ad selection starts with what is being discussed in the current chat thread. It also says that, if the user enables personalization, OpenAI may use:
- the current chat thread
- personalized model responses
- past chats and memory
- how the user interacts with ads
- general location and language
That gives us a likely ranking pipeline.
Step 1: conversation understanding
The system needs to derive structured ad signals from unstructured dialogue. That usually means topic extraction, intent detection, and policy classification.
For example:
type ConversationSignals = {
topics: string[];
commercialIntent: "none" | "low" | "medium" | "high";
locale: string;
language: string;
safetyClass: "safe" | "sensitive" | "regulated" | "disallowed";
};
function deriveConversationSignals(thread: ChatTurn[]): ConversationSignals {
return {
topics: ["travel planning", "tokyo hotels", "family itinerary"],
commercialIntent: "high",
locale: "US",
language: "en",
safetyClass: "safe",
};
}
The exact implementation could be rule-based, embedding-based, classifier-based, or hybrid. OpenAI has not said which. But some kind of conversation-to-signals transformation has to happen, because ad retrieval cannot operate directly on arbitrary chat text at scale.
Step 2: placement safety and policy gating
This is where conversational advertising gets much stricter than standard web inventory.
OpenAI’s ad policy explicitly blocks ad placement in high-risk contexts, including:
- mental health conversations
- politically sensitive content
- vulnerable user journeys
- misinformation
- self-harm
- regulated goods and services
- other brand-unsafe contexts
So even if the conversation contains obvious buying intent, the ad engine should short-circuit if the topic is sensitive.
That gating logic probably resembles:
function isAdPlacementAllowed(safetyClass: ConversationSignals["safetyClass"]) {
return safetyClass === "safe";
}
The real production version would be more granular, but the principle is the same: relevance is subordinate to policy.
Step 3: candidate retrieval
Once a chat is eligible, the system needs candidate ads from approved advertiser inventory.
This is where OpenAI’s public ad policy matters. The allowed inventory is currently narrow. At launch, OpenAI says ads are primarily limited to categories such as:
- household and consumer goods
- local services
- travel and experiences
- digital products and education
That means the retrieval layer is not searching across the full ad-tech universe. It is searching a curated, policy-screened subset.
A plausible retrieval query:
SELECT ad_id, advertiser_id, landing_url, targeting_profile
FROM approved_ads
WHERE market = 'US'
AND status = 'active'
AND vertical IN ('local_services', 'travel', 'consumer_goods', 'digital_products')
AND topic_overlap(targeting_profile, :conversation_topics) > 0
AND age_restricted = false
AND sensitive_category = false;
Again, this is illustrative, not leaked implementation.
Step 4: ranking
OpenAI has publicly said that if multiple advertisers are eligible, it will show the one most relevant to the chat first.
That implies a ranking function over candidate ads.
A conventional ranking score might combine:
- match to current thread topics
- match to language and market
- user-level feedback like prior hides or dismissals
- personalization features if enabled
- inventory quality or policy confidence
- pacing or budget controls
For example:
function scoreAd(req: AdRequest, ad: CandidateAd): number {
let score = 0;
score += topicSimilarity(req.signals.current_thread_topics, ad.targetTopics) * 0.50;
score += marketMatch(req.market, ad.market) * 0.15;
score += languageMatch(req.language, ad.language) * 0.10;
score += personalizationLift(req, ad) * 0.15;
score += qualityScore(ad) * 0.10;
score -= negativeFeedbackPenalty(req, ad);
return score;
}
The exact weights are unknown. What is clear is the priority order:
- policy eligibility
- contextual relevance
- user control and feedback
- rendering a single clearly separated unit
That is a very different objective from engagement-maximizing feed ads.
Does the model itself choose the ad?
Publicly, OpenAI says no in the important sense.
OpenAI states that ads run on separate systems from the chat model, and that advertisers cannot influence, rank, or alter the answer. That means the model may still be used somewhere in the pipeline for classification, topic extraction, or safety understanding, but the ad decisioning system is not the same thing as the answer generation system.
That distinction is critical.
A cleaner mental model is:
- the LLM produces the answer
- a separate ad stack evaluates whether a sponsored unit may be shown
- the UI compositor places the ad below the answer
In other words, OpenAI is trying to preserve a strict boundary between assistant utility and commercial placement.
How personalization likely works
OpenAI’s documentation is unusually explicit here. If ad personalization is enabled, the system may use:
- past chats
- memory
- ad interaction history
- current thread context
- personalized responses
If personalization is turned off, OpenAI says the system still uses the current chat thread, but not other threads, ad history, or interests.
That suggests a feature-flagged decision path:
function buildAdFeatures(user: UserState, thread: ChatThread): AdFeatures {
const base = {
currentThreadTopics: extractTopics(thread),
language: user.language,
region: user.region,
};
if (!user.personalizedAdsEnabled) {
return base;
}
return {
...base,
memoryTopics: user.memoryTopics,
priorAdInteractions: user.adInteractionHistory,
historicalInterests: user.interests,
};
}
This is likely why OpenAI exposes controls like:
Personalize adsPast chats and memoryDelete ads dataAbout this ad
That is not just a UX choice. It reflects how the feature store for ad relevance is partitioned.
The attribution chain: what happens after an ad is shown
This is where most ad-tech stacks become opaque. OpenAI’s public description is more privacy-constrained than the standard web ad market.
What OpenAI has said publicly
OpenAI says advertisers receive:
- aggregated
- non-identifying
- performance reporting such as views and clicks
It also says advertisers do not receive:
- chats
- chat history
- memories
- name
- precise location
- IP address
- sensitive information
That means the publicly documented attribution chain is currently much closer to:
impression -> click -> aggregated advertiser reporting
than to the typical ad-tech sprawl of:
impression -> click id -> redirect chain -> cookie sync -> remarketing audience -> postback -> MTA dashboard -> data broker enrichment
At least from the public documentation, OpenAI is intentionally not describing that second style of system.
A practical event model
If you were designing this stack conservatively, the event schema could look like:
type AdImpressionEvent = {
eventId: string;
adId: string;
advertiserId: string;
conversationPlacement: "below_response";
market: string;
timestamp: string;
personalized: boolean;
};
type AdClickEvent = {
eventId: string;
impressionEventId: string;
adId: string;
advertiserId: string;
timestamp: string;
};
And the reporting layer exposed to advertisers would aggregate those:
SELECT
advertiser_id,
ad_id,
COUNT(*) FILTER (WHERE event_type = 'impression') AS impressions,
COUNT(*) FILTER (WHERE event_type = 'click') AS clicks
FROM ad_events
WHERE event_date BETWEEN :start AND :end
GROUP BY advertiser_id, ad_id;
That fits what OpenAI has disclosed: aggregate views and clicks, not user-level transcript exports.
What we do not know
OpenAI has not publicly documented, at least in the sources used here:
- whether advertisers get impression-level logs
- whether click redirects contain persistent campaign identifiers visible to advertisers
- whether external conversion APIs exist
- whether there is post-click purchase attribution beyond aggregate engagement
- whether billing is CPM, CPC, CPA, or hybrid
- whether ranking includes auction pricing or is mostly relevance- and policy-driven during the pilot
Those are normal questions for an ad platform. They are just not yet publicly answered.
So if someone claims to know OpenAI’s full attribution chain end to end, they are either working from non-public information or overreaching.
The most important privacy boundary
The core architectural promise OpenAI keeps repeating is:
- chat content may be used inside ChatGPT to select a relevant ad
- that same content is not handed to the advertiser
That is a subtle but major distinction.
It means OpenAI is using conversation context as an internal relevance signal, not exposing the conversation as advertiser-readable targeting payload.
That is closer to:
user conversation -> OpenAI internal feature extraction -> ad match
than to:
user conversation -> raw transcript sent to advertiser -> advertiser chooses ad
OpenAI explicitly rejects the second model in its public help documentation.
Why OpenAI’s ad design is stricter than normal ad-tech
There are at least four reasons.
1. The conversation is much more sensitive than a page view
A search query is often short and disposable. A ChatGPT thread can contain:
- financial planning
- relationship questions
- health concerns
- work strategy
- personal vulnerability
That makes contextual monetization much riskier.
2. The assistant relationship is easy to corrupt
If the user suspects the answer is being bent toward a sponsor, trust collapses fast. That is why OpenAI emphasizes answer independence so heavily.
3. Memory raises the stakes
Past-chat personalization is much richer than a normal browsing cookie. That creates better relevance potential, but also much more scrutiny around consent and controls.
4. Ad adjacency can become a policy problem immediately
On the open web, a bad page-ad pairing is embarrassing. In a conversational AI system, it can be exploitative.
That is why OpenAI’s published placement rules are full of negative eligibility logic.
A realistic mental model for engineers
If you are an engineer or product person, the safest way to think about OpenAI’s ad stack in 2026 is:
LLM answer system
!=
Ad decisioning system
Ad decisioning system
=
policy filters
+ conversation understanding
+ approved inventory retrieval
+ relevance ranking
+ privacy-constrained reporting
That is the right abstraction.
Not because it is glamorous, but because it matches the evidence.
Final take
OpenAI’s ad system, as publicly described today, is not a generic surveillance-ad clone dropped into a chatbot. It looks more like a tightly constrained conversational ad layer with:
- response-ad separation
- conversation-aware targeting
- aggressive sensitive-topic exclusions
- explicit personalization controls
- aggregate-only advertiser reporting, at least publicly
The technical novelty is not that OpenAI can show ads. Every consumer platform can do that.
The novelty is that ChatGPT has to choose ads from a live conversation without letting the monetization logic contaminate the answer, violate user trust, or expose raw conversational data to advertisers.
That is a much harder systems design problem than standard display advertising.
And for now, OpenAI appears to be solving it with a conservative pilot: one ad unit, below the answer, policy-heavy gating, and a deliberately narrow attribution surface.
If OpenAI later publishes more about billing models, conversion measurement, advertiser APIs, or auction mechanics, the real ad-tech story will become clearer. As of April 29, 2026, the public documentation supports a strong explanation of selection inputs, placement rules, and privacy boundaries, but only a limited explanation of full-funnel attribution.