01
Quick start
1. Install the SDK
npm install @agentads/sdk # or yarn add @agentads/sdk # or pnpm add @agentads/sdk
2. Get your API key
Sign up at app.tryagentads.com and copy your publisher API key from the Integration page.
# .env.local AGENTADS_KEY=pub_live_xxxxxxxxxxxxxxxxxxxx
3. Wrap your model (Vercel AI SDK)
import { openai } from '@ai-sdk/openai'
import { withAgentAds } from '@agentads/sdk'
// Drop-in replacement — same API, same streaming
const model = withAgentAds(openai('gpt-4o'), {
publisherApiKey: process.env.AGENTADS_KEY!,
})
// Use exactly like before
const result = await generateText({ model, prompt: userMessage })
// result.text now includes a contextual ad if matched
// → "...your answer...
---
**Sponsored:** Clerk — Auth in 5 minutes..."That's it.
The SDK runs a 50ms real-time auction in the background. If a relevant ad is found, it's appended after the AI response. If not (no fill, timeout, or low-intent query), nothing happens. Your users never experience latency.
02
React component
If you're building a React or Next.js chat UI, use the drop-in <AgentAd /> component. It handles fetching, rendering, and click tracking automatically. Shows nothing on no-fill — zero layout shift.
Basic usage
import { AgentAd } from '@agentads/sdk/react'
export function ChatMessage({ query, response }: { query: string; response: string }) {
return (
<div>
<p>{response}</p>
{/* Renders a sponsored card after each assistant message */}
<AgentAd
publisherApiKey={process.env.NEXT_PUBLIC_AGENTADS_KEY!}
query={query}
response={response}
/>
</div>
)
}What it renders
Add sign-in, user management, and MFA to your app with 4 lines of code. Free up to 10k MAU.
All props
| Prop | Type | Description |
|---|---|---|
| publisherApiKey | string | Your publisher API key (required) |
| query | string | The user's message or prompt |
| response | string | The AI response text (first 200 chars used) |
| apiUrl | string? | Override API URL (default: api.tryagentads.com) |
| timeout | number? | Auction timeout in ms (default: 50) |
Next.js example — after assistant messages
// components/messages.tsx
import { AgentAd } from '@agentads/sdk/react'
export function Messages({ messages }: { messages: Message[] }) {
return messages.map((msg, i) => {
const prevMsg = messages[i - 1]
return (
<div key={msg.id}>
<MessageBubble message={msg} />
{/* Show ad after each assistant response */}
{msg.role === 'assistant' && (
<AgentAd
publisherApiKey={process.env.NEXT_PUBLIC_AGENTADS_KEY!}
query={prevMsg?.role === 'user' ? prevMsg.content : ''}
response={msg.content}
/>
)}
</div>
)
})
}03
Node.js / fetch API
Use fetchAd() for full control — works in any Node.js environment, edge functions, or server-side code.
import { fetchAd } from '@agentads/sdk'
const ad = await fetchAd({
publisherApiKey: process.env.AGENTADS_KEY!,
query: userMessage,
response: aiResponse, // first 200 chars used for classification
timeout: 50, // ms — never delays your response
})
if (ad) {
// Append to your response however you like
const sponsored = `\n\n---\n**Sponsored:** ${ad.headline}\n${ad.description} — [${ad.ctaText}](${ad.clickUrl})`
return aiResponse + sponsored
}
// ad === null → no fill, timeout, or error — safe to ignoreManual fetch (no SDK)
const res = await fetch('https://api.tryagentads.com/bid', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Publisher-Key': 'pub_live_...',
},
body: JSON.stringify({
query: userMessage,
response: aiResponse.slice(0, 200),
format: 'suffix', // 'suffix' | 'citation' | 'followup'
}),
signal: AbortSignal.timeout(50),
})
const data = await res.json()
// data.filled === true → data.ad has headline, description, cta, clickUrl
// data.filled === false → no auction winnerPython (requests)
import requests
try:
r = requests.post(
'https://api.tryagentads.com/bid',
headers={'X-Publisher-Key': 'pub_live_...'},
json={'query': user_message, 'response': ai_response[:200]},
timeout=0.05 # 50ms
)
data = r.json()
if data.get('filled') and data.get('ad'):
ad = data['ad']
sponsored = f"\n\n---\nSponsored: {ad['headline']} — {ad['cta']}: {ad['clickUrl']}"
response_text += sponsored
except requests.exceptions.Timeout:
pass # No ad — always safe to ignore04
Conversion tracking
Track when a user converts after clicking your ad. Works automatically — when a user clicks an ad, we append ?aads_tid=... and ?aads_token=... to the destination URL. The pixel on the advertiser's thank-you page reads them and records the conversion.
This is an advertiser feature
Publishers don't need to do anything. The tracking params are appended automatically by AgentAds on every ad click. Advertisers get the conversion pixel snippet in their campaign analytics dashboard.
Advertiser pixel — paste on your thank-you / confirmation page
<!-- AgentAds Conversion Pixel -->
<script>
(function() {
var params = new URLSearchParams(window.location.search);
var tid = params.get('aads_tid');
var token = params.get('aads_token');
if (!tid || !token) return;
new Image().src =
'https://api.tryagentads.com/v1/convert' +
'?tid=' + encodeURIComponent(tid) +
'&token=' + encodeURIComponent(token) +
'&value=VALUE_CENTS'; // replace with order value, e.g. 4900 for $49
})();
</script>How it works
- 1User sees your ad in an AI response and clicks it
- 2AgentAds appends ?aads_tid=TRACKING_ID&aads_token=HMAC_TOKEN to your destination URL
- 3User lands on your site with those params in the URL
- 4On your thank-you page, the pixel reads the params and fires a 1px request to api.tryagentads.com/v1/convert
- 5Conversion is logged to your campaign — you see conversions + ROAS in your dashboard
Attribution window
30-day attribution. Conversions are deduplicated by tracking ID — one conversion per click, regardless of how many times the pixel fires. The HMAC token prevents fake conversion submissions.
05
API reference
/bid— Request an adBase URL: https://api.tryagentads.com
Request headers
| Header | Value |
|---|---|
| Content-Type | application/json |
| X-Publisher-Key | pub_live_... |
Request body
| Field | Type | Description |
|---|---|---|
| query | string | The user's message or prompt (required) |
| response | string | AI response text, first 200 chars used (required) |
| format | 'suffix' | 'citation' | 'followup' | Ad placement format (default: suffix) |
| sessionId | string? | Hashed session ID for frequency capping |
Response
// filled
{
"filled": true,
"requestId": "abc123",
"ad": {
"format": "suffix",
"headline": "Clerk — Auth in 5 minutes",
"description": "Add sign-in and user management with 4 lines of code.",
"cta": "Get started free",
"clickUrl": "https://api.tryagentads.com/click/track_xyz",
"label": "Ad"
}
}
// no fill
{
"filled": false,
"requestId": "abc123"
}/v1/convert— Record a conversion| Param | Description |
|---|---|
| tid | Tracking ID from ?aads_tid URL param |
| token | HMAC token from ?aads_token URL param |
| value | Conversion value in cents (e.g. 4900 for $49) |
Returns a 1×1 transparent GIF. Deduped by tracking ID. HMAC-verified to prevent forgery.