Custom GPT Integration Guide
This guide explains how to integrate the In-Chat Recommendations API into a Custom GPT experience.
It covers:
- What a Custom GPT can and cannot do
- Recommended architecture (client/server)
- How to call the API with GPT Actions
- How to render ads and report impressions correctly
1) What You’re Building
You are integrating ads (recommendations) into a chat conversation:
- The user chats with your Custom GPT.
- Your Custom GPT triggers an API call to fetch ads that match the conversation context.
- Your UI renders the ads as cards/links.
- You fire the
reportServedimpression pixel for displayed ads.
2) Custom GPT Capabilities (Important)
A Custom GPT can:
✅ Call external APIs via Actions
✅ Format structured output (JSON) for your UI
✅ Decide when to request ads (based on conversation context)
A Custom GPT cannot:
❌ Execute navigator.sendBeacon() directly
❌ Fire browser pixels itself
❌ Reliably access a user’s browsing environment
✅ Therefore:
- The GPT should fetch ads
- Your frontend (or host app) should render ads and fire pixels
3) Recommended Architecture
Option A (Recommended): Custom GPT + Backend Proxy + Frontend UI
Custom GPT → Your backend proxy → In-Chat Recs API
│ │
└────────→ UI renders ads + fires reportServed pixel
Why this is best:
- Keeps
keysecure (not exposed client-side) - Allows logging, monitoring, retries
- Enables safer filtering of keywords/categories
Option B: Custom GPT calls API directly
Possible, but only recommended if:
- Key exposure is acceptable for your use case
- You cannot deploy a backend proxy
4) What You Send to the API
Endpoint
Method: POST
URL:
https://mv.outbrain.com/Multivac/api/in-chat-recs
Query Parameters
| Parameter | Required | Description |
|---|---|---|
key | ✅ | Your API key |
contentUrl | ✅ | URL-encoded host page (e.g., test.com) |
widgetJSId | ✅ | Provided by Teads (e.g., APP_12) |
cors | ✅ | Must be true |
testMode | ❌ | Use true in dev/testing |
JSON Body
{
"keywords": ["investing", "savings", "personal finance"],
"iabCategories": ["IAB13"]
}
5) Configure a Custom GPT Action (OpenAPI Spec)
In the Custom GPT builder:
- Open Actions
- Add a new Action using an OpenAPI schema
- Point it at your backend proxy (recommended)
Example Action Endpoint (Proxy)
POST https://yourdomain.com/api/teads/in-chat-recs
Minimal OpenAPI Example
openapi: 3.0.3
info:
title: In-Chat Recommendations API Proxy
version: 1.0.0
servers:
- url: https://yourdomain.com
paths:
/api/teads/in-chat-recs:
post:
operationId: fetchInChatRecs
summary: Fetch in-chat ad recommendations
parameters:
- name: contentUrl
in: query
required: true
schema:
type: string
description: URL-encoded host page (e.g., test.com)
- name: testMode
in: query
required: false
schema:
type: boolean
description: Enable dev test mode
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
keywords:
type: array
items:
type: string
iabCategories:
type: array
items:
type: string
responses:
"200":
description: Recommendations response
content:
application/json:
schema:
type: object
✅ Your backend proxy should inject:
keywidgetJSIdcors=true
So the GPT never sees your secrets.
6) Backend Proxy (Recommended)
Your backend receives:
contentUrlkeywordsiabCategories- optional
testMode
Then it calls:
https://mv.outbrain.com/Multivac/api/in-chat-recs?key=...&contentUrl=...&widgetJSId=APP_12&cors=true
✅ Benefits:
- API key stays hidden
- You can filter keywords to prevent sensitive data leakage
- You can standardize
contentUrlto the host domain only
7) Rendering Ads in Your UI
Your UI should render each item in documents[] as an Ad Card:
- Clickable link (
url) - Creative image (
thumbnail_url) - Title (
content) - Sponsor label (
source_display_name) - Optional domain (
target_domain) - Optional CTA button (
cta)
Example UI pseudo-structure:
[thumbnail]
Title: content
Sponsored by source_display_name (target_domain)
[CTA button]
8) Reporting Impressions (Required)
Once ads are rendered, report impressions using the tracking URL:
- Read
reportServed - Append positions of displayed ads:
&pos=X-Y - Fire the pixel as GET or
navigator.sendBeacon
Example
If displayed ads have pos: 0 and pos: 2:
{reportServed}&pos=0-2
Browser Pixel Example
function reportServed(reportServedUrl, displayedAds) {
if (!reportServedUrl) return;
const pos = displayedAds.map(a => a.pos).join("-");
const pixel = `${reportServedUrl}&pos=${pos}`;
navigator.sendBeacon(pixel);
}
9) Suggested Prompting Pattern for the Custom GPT
To keep behavior consistent, add instruction text like:
System/Developer Guidance
- Extract 3–10 topic keywords from the conversation context
- Choose 1–2 IAB categories when possible
- Avoid personal data, names, emails, addresses, account IDs
- Call the
fetchInChatRecsaction when the conversation is commercially relevant - Return the response in a structured format for the UI to render
Example output schema your GPT can produce:
{
"ads": [
{
"title": "content",
"image": "thumbnail_url",
"clickUrl": "url",
"sponsor": "source_display_name",
"domain": "target_domain",
"cta": "cta",
"pos": 0
}
],
"reportServed": "tracking.reportServed"
}
10) End-to-End Example Flow
- User asks: “Any advice for saving money?”
- GPT generates contextual signals:
- keywords: ["budgeting", "savings", "personal finance"]
- iabCategories: ["IAB13"]
- GPT calls Action:
fetchInChatRecs - UI renders 2 ads (positions 0 and 1)
- UI fires:
{reportServed}&pos=0-1
11) Safety + Privacy Guidelines (Must Follow)
✅ DO:
- Send only topic keywords
- Avoid copying raw user chat text
- Do not include personal identifiers in requests
- Keep
keysecret (proxy recommended)
❌ DO NOT:
- Send user names/emails/phone numbers
- Send full chat transcripts
- Attach user IDs, session IDs, or precise location
12) Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
| Action fails | Proxy URL or schema mismatch | Validate OpenAPI + endpoint |
| 403 from partner | Invalid/missing API key | Ensure backend injects key |
| No ads returned | Invalid contentUrl or widget | Verify domain + APP_12 |
| Impressions not counted | Pixel not fired or wrong pos format | Use &pos=X-Y for displayed ads |
© 2026 Teads AI Platform. All rights reserved.