@the_ro_show/agent-ads-sdk 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +309 -388
- package/SIMPLE_INTEGRATION_GUIDE.md +11 -16
- package/dist/index.d.mts +62 -1
- package/dist/index.d.ts +62 -1
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +62 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,553 +1,474 @@
|
|
|
1
1
|
# AttentionMarket Agent Ads SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@the_ro_show/agent-ads-sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
**The first ad network built for AI agents.** Monetize your AI agent with contextual, high-intent sponsored suggestions. Open source, transparent, developer-first.
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
- 🚀 **5-minute integration** - npm install + 5 lines of code
|
|
10
|
+
- 💰 **70% revenue share** - You keep the majority, we only win when you do
|
|
11
|
+
- 🎯 **10-15% CTR** - High-intent placements, not banner ads
|
|
12
|
+
- 🔓 **100% Open Source** - Audit every line, full transparency
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
---
|
|
14
|
+
## Quick Start
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
### 1. Get Your API Key
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
npm install @the_ro_show/agent-ads-sdk
|
|
17
|
-
```
|
|
18
|
+
**Sign up at [attentionmarket.com/signup](https://attentionmarket.com/signup)** (30 seconds, free forever)
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
You'll receive:
|
|
21
|
+
- Test key: `am_test_...` (for development)
|
|
22
|
+
- Live key: `am_live_...` (for production)
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
### 2. Install
|
|
22
25
|
|
|
23
26
|
```bash
|
|
24
|
-
|
|
25
|
-
export ATTENTIONMARKET_AGENT_ID=agt_01HV...
|
|
27
|
+
npm install @the_ro_show/agent-ads-sdk
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
## Quick Start
|
|
30
|
+
### 3. Integrate (5 lines of code)
|
|
31
31
|
|
|
32
32
|
```typescript
|
|
33
|
-
import { AttentionMarketClient,
|
|
34
|
-
|
|
35
|
-
const client = new AttentionMarketClient({ apiKey: process.env.ATTENTIONMARKET_API_KEY });
|
|
33
|
+
import { AttentionMarketClient, detectIntent, buildTaxonomy } from '@the_ro_show/agent-ads-sdk';
|
|
36
34
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
country: 'US',
|
|
40
|
-
language: 'en',
|
|
41
|
-
platform: 'web',
|
|
42
|
-
query: 'Find movers in Brooklyn',
|
|
35
|
+
const client = new AttentionMarketClient({
|
|
36
|
+
apiKey: process.env.ATTENTIONMARKET_API_KEY // Your test or live key
|
|
43
37
|
});
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
// When your agent helps users, show relevant ads
|
|
40
|
+
const userQuery = "I need car insurance for my Honda";
|
|
41
|
+
const intent = detectIntent(userQuery); // → "quote" or "compare" or "research"
|
|
42
|
+
const taxonomy = buildTaxonomy('insurance', 'auto', 'full_coverage', intent);
|
|
43
|
+
|
|
44
|
+
const decision = await client.decide({
|
|
45
|
+
request_id: crypto.randomUUID(),
|
|
46
|
+
agent_id: 'your_agent_id',
|
|
47
|
+
placement: { type: 'sponsored_suggestion' },
|
|
48
|
+
opportunity: {
|
|
49
|
+
intent: { taxonomy }, // "insurance.auto.full_coverage.quote"
|
|
50
|
+
context: { country: 'US', language: 'en', platform: 'web' }
|
|
51
|
+
}
|
|
50
52
|
});
|
|
51
53
|
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
console.log(
|
|
55
|
-
|
|
56
|
-
await client.trackImpression({
|
|
57
|
-
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
58
|
-
request_id: 'req_id',
|
|
59
|
-
decision_id: 'decision_id',
|
|
60
|
-
unit_id: unit.unit_id,
|
|
61
|
-
tracking_token: unit.tracking.token,
|
|
62
|
-
});
|
|
54
|
+
if (decision.status === 'filled') {
|
|
55
|
+
const ad = decision.units[0];
|
|
56
|
+
console.log(`[Sponsored] ${ad.suggestion.title}`);
|
|
57
|
+
// User clicks → You earn $5-50
|
|
63
58
|
}
|
|
64
59
|
```
|
|
65
60
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
🔴 **CRITICAL SECURITY REQUIREMENTS**
|
|
61
|
+
**That's it!** Start earning from relevant ads.
|
|
69
62
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
**This SDK MUST only be used server-side.** Your API key provides full access to your account and billing.
|
|
63
|
+
---
|
|
73
64
|
|
|
74
|
-
|
|
75
|
-
❌ **Unsafe:** Browser JavaScript, mobile apps without backend proxy
|
|
65
|
+
## 🆕 What's New in v0.4.0
|
|
76
66
|
|
|
77
|
-
###
|
|
67
|
+
### Hierarchical Taxonomy Matching
|
|
78
68
|
|
|
79
|
-
|
|
69
|
+
Target broadly, match specifically:
|
|
80
70
|
|
|
81
71
|
```typescript
|
|
82
|
-
|
|
72
|
+
// Advertiser targets: "insurance.auto"
|
|
73
|
+
// Your agent requests: "insurance.auto.full_coverage.quote"
|
|
74
|
+
// ✅ Matches! (0.7 relevance score)
|
|
83
75
|
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
const safeBody = escapeHTML(unit.suggestion.body);
|
|
87
|
-
const safeURL = sanitizeURL(unit.suggestion.action_url);
|
|
76
|
+
// Your agent requests: "insurance.auto.liability.compare"
|
|
77
|
+
// ✅ Also matches! (0.7 relevance score)
|
|
88
78
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
79
|
+
// Your agent requests: "insurance.home.flood.quote"
|
|
80
|
+
// ❌ No match (different category)
|
|
92
81
|
```
|
|
93
82
|
|
|
94
|
-
|
|
95
|
-
// ❌ DANGEROUS: Direct HTML injection (XSS vulnerability!)
|
|
96
|
-
element.innerHTML = unit.suggestion.title;
|
|
97
|
-
```
|
|
83
|
+
**Result:** 3x more ad inventory, higher fill rates.
|
|
98
84
|
|
|
99
|
-
###
|
|
100
|
-
|
|
101
|
-
Always validate `action_url` before using:
|
|
85
|
+
### New Helper Functions
|
|
102
86
|
|
|
87
|
+
**Auto-detect user intent:**
|
|
103
88
|
```typescript
|
|
104
|
-
|
|
89
|
+
import { detectIntent } from '@the_ro_show/agent-ads-sdk';
|
|
105
90
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
91
|
+
detectIntent("What is car insurance?") // → 'research'
|
|
92
|
+
detectIntent("Compare car insurance options") // → 'compare'
|
|
93
|
+
detectIntent("Get car insurance quote") // → 'quote'
|
|
94
|
+
detectIntent("I want to buy car insurance") // → 'apply'
|
|
110
95
|
```
|
|
111
96
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
97
|
+
**Build taxonomies easily:**
|
|
98
|
+
```typescript
|
|
99
|
+
import { buildTaxonomy } from '@the_ro_show/agent-ads-sdk';
|
|
115
100
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
- Rate limiting
|
|
120
|
-
- Input validation
|
|
121
|
-
- Security checklist
|
|
101
|
+
const taxonomy = buildTaxonomy('insurance', 'auto', 'full_coverage', 'quote');
|
|
102
|
+
// → "insurance.auto.full_coverage.quote"
|
|
103
|
+
```
|
|
122
104
|
|
|
123
|
-
|
|
105
|
+
**Get taxonomy suggestions:**
|
|
106
|
+
```typescript
|
|
107
|
+
import { suggestTaxonomies } from '@the_ro_show/agent-ads-sdk';
|
|
124
108
|
|
|
125
|
-
|
|
109
|
+
const suggestions = suggestTaxonomies("I need a lawyer for divorce");
|
|
110
|
+
// → ['legal.family.divorce.consultation', 'legal.family.custody.consultation']
|
|
111
|
+
```
|
|
126
112
|
|
|
113
|
+
**Validate taxonomies:**
|
|
127
114
|
```typescript
|
|
128
|
-
import {
|
|
115
|
+
import { isValidTaxonomy, parseTaxonomy } from '@the_ro_show/agent-ads-sdk';
|
|
129
116
|
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
latencyMs: 100, // Simulate API latency
|
|
133
|
-
fillRate: 1.0, // 100% fill rate for testing
|
|
134
|
-
verbose: true, // Log mock activity
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
const opportunity = createOpportunity({
|
|
138
|
-
taxonomy: 'local_services.movers.quote',
|
|
139
|
-
country: 'US',
|
|
140
|
-
language: 'en',
|
|
141
|
-
platform: 'web',
|
|
142
|
-
query: 'Find movers in Brooklyn',
|
|
143
|
-
});
|
|
117
|
+
isValidTaxonomy('insurance.auto.full_coverage.quote') // → true
|
|
118
|
+
isValidTaxonomy('invalid.format') // → false
|
|
144
119
|
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
agent_id: 'agt_test',
|
|
148
|
-
placement: { type: 'sponsored_suggestion', surface: 'chat_response' },
|
|
149
|
-
opportunity,
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// Returns realistic mock ad data immediately
|
|
153
|
-
if (unit && unit.unit_type === 'sponsored_suggestion') {
|
|
154
|
-
console.log(unit.suggestion.title); // "Professional Moving Services - Same Day Available"
|
|
155
|
-
}
|
|
120
|
+
const parsed = parseTaxonomy('insurance.auto.full_coverage.quote');
|
|
121
|
+
// → { vertical: 'insurance', category: 'auto', subcategory: 'full_coverage', intent: 'quote' }
|
|
156
122
|
```
|
|
157
123
|
|
|
158
|
-
|
|
159
|
-
- `local_services.movers.quote`
|
|
160
|
-
- `local_services.restaurants.search`
|
|
161
|
-
- `local_services.plumbers.quote`
|
|
162
|
-
- `local_services.electricians.quote`
|
|
163
|
-
- `local_services.cleaners.quote`
|
|
164
|
-
- `shopping.electronics.search`
|
|
124
|
+
---
|
|
165
125
|
|
|
166
|
-
|
|
126
|
+
## Common Taxonomies
|
|
167
127
|
|
|
128
|
+
### Insurance ($20-54 CPC)
|
|
168
129
|
```typescript
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
suggestion: {
|
|
175
|
-
title: 'Your Ad Title',
|
|
176
|
-
body: 'Your ad body text',
|
|
177
|
-
cta: 'Call to Action',
|
|
178
|
-
action_url: 'https://example.com',
|
|
179
|
-
},
|
|
180
|
-
});
|
|
130
|
+
'insurance.auto.full_coverage.quote'
|
|
131
|
+
'insurance.auto.liability.compare'
|
|
132
|
+
'insurance.home.standard.quote'
|
|
133
|
+
'insurance.life.term.compare'
|
|
134
|
+
'insurance.health.individual.quote'
|
|
181
135
|
```
|
|
182
136
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
137
|
+
### Legal ($50-150 CPC)
|
|
138
|
+
```typescript
|
|
139
|
+
'legal.personal_injury.accident.consultation'
|
|
140
|
+
'legal.family.divorce.consultation'
|
|
141
|
+
'legal.criminal.defense.consultation'
|
|
142
|
+
'legal.immigration.visa.consultation'
|
|
143
|
+
'legal.estate_planning.will.consultation'
|
|
187
144
|
```
|
|
188
145
|
|
|
189
|
-
|
|
190
|
-
|
|
146
|
+
### Financial Services ($15-50 CPC)
|
|
191
147
|
```typescript
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
148
|
+
'financial.loans.personal.quote'
|
|
149
|
+
'financial.loans.mortgage.compare'
|
|
150
|
+
'financial.credit_cards.rewards.compare'
|
|
151
|
+
'financial.investing.brokerage.trial'
|
|
195
152
|
```
|
|
196
153
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
- **[OpenAI GPT](./examples/openai-function-calling-minimal.ts)** - Minimal function calling
|
|
205
|
-
- **[Google Gemini](./examples/gemini-function-calling-minimal.ts)** - Minimal function declarations
|
|
206
|
-
|
|
207
|
-
Each shows: `createOpportunity` → `decide` → render → track
|
|
208
|
-
|
|
209
|
-
### Full Examples (with detailed integration notes)
|
|
154
|
+
### B2B SaaS ($10-100 CPC)
|
|
155
|
+
```typescript
|
|
156
|
+
'business.saas.crm.trial'
|
|
157
|
+
'business.saas.project_management.trial'
|
|
158
|
+
'business.ecommerce.platform.trial'
|
|
159
|
+
'business.saas.marketing_automation.trial'
|
|
160
|
+
```
|
|
210
161
|
|
|
211
|
-
|
|
162
|
+
### Home Services ($5-30 CPC)
|
|
163
|
+
```typescript
|
|
164
|
+
'home_services.moving.local.quote'
|
|
165
|
+
'home_services.cleaning.regular.book'
|
|
166
|
+
'home_services.plumbing.emergency.quote'
|
|
167
|
+
'home_services.remodeling.kitchen.quote'
|
|
168
|
+
```
|
|
212
169
|
|
|
213
|
-
|
|
214
|
-
- **[OpenAI GPT](./examples/openai-function-calling-full.ts)** - Complete function calling with integration checklist
|
|
215
|
-
- **[Google Gemini](./examples/gemini-function-calling-full.ts)** - Complete function declarations with testing guide
|
|
216
|
-
- **[Safe Web Rendering](./examples/safe-web-rendering.ts)** - XSS prevention and secure HTML rendering
|
|
170
|
+
**See all 50+ taxonomies:** [TAXONOMY_SYSTEM.md](./TAXONOMY_SYSTEM.md)
|
|
217
171
|
|
|
218
|
-
|
|
219
|
-
```bash
|
|
220
|
-
npx tsx examples/claude-tool-use-minimal.ts
|
|
221
|
-
npx tsx examples/safe-web-rendering.ts
|
|
222
|
-
```
|
|
172
|
+
---
|
|
223
173
|
|
|
224
|
-
##
|
|
174
|
+
## Complete Example
|
|
225
175
|
|
|
226
176
|
```typescript
|
|
227
177
|
import {
|
|
228
178
|
AttentionMarketClient,
|
|
229
|
-
|
|
230
|
-
|
|
179
|
+
buildTaxonomy,
|
|
180
|
+
detectIntent
|
|
231
181
|
} from '@the_ro_show/agent-ads-sdk';
|
|
232
182
|
|
|
233
183
|
const client = new AttentionMarketClient({
|
|
234
|
-
apiKey: process.env.ATTENTIONMARKET_API_KEY
|
|
184
|
+
apiKey: process.env.ATTENTIONMARKET_API_KEY
|
|
235
185
|
});
|
|
236
186
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
187
|
+
async function showRelevantAd(userQuery: string) {
|
|
188
|
+
// 1. Detect what the user wants
|
|
189
|
+
const intent = detectIntent(userQuery);
|
|
190
|
+
|
|
191
|
+
// 2. Build taxonomy (or use your own logic)
|
|
192
|
+
let taxonomy: string;
|
|
193
|
+
if (/insurance|car|auto/i.test(userQuery)) {
|
|
194
|
+
taxonomy = buildTaxonomy('insurance', 'auto', 'full_coverage', intent);
|
|
195
|
+
} else if (/lawyer|legal|divorce/i.test(userQuery)) {
|
|
196
|
+
taxonomy = buildTaxonomy('legal', 'family', 'divorce', 'consultation');
|
|
197
|
+
} else {
|
|
198
|
+
return null; // No relevant ads
|
|
199
|
+
}
|
|
245
200
|
|
|
246
|
-
//
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
201
|
+
// 3. Request ads
|
|
202
|
+
const decision = await client.decide({
|
|
203
|
+
request_id: crypto.randomUUID(),
|
|
204
|
+
agent_id: 'your_agent_id',
|
|
205
|
+
placement: { type: 'sponsored_suggestion' },
|
|
206
|
+
opportunity: {
|
|
207
|
+
intent: { taxonomy },
|
|
208
|
+
context: {
|
|
209
|
+
country: 'US',
|
|
210
|
+
language: 'en',
|
|
211
|
+
platform: 'web'
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
256
215
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
console.log(`Units: ${response.units.length}`);
|
|
216
|
+
// 4. Show ad if available
|
|
217
|
+
if (decision.status === 'filled') {
|
|
218
|
+
const ad = decision.units[0];
|
|
261
219
|
|
|
262
|
-
|
|
220
|
+
console.log(`\n[${ad.disclosure.label}] ${ad.disclosure.sponsor_name}`);
|
|
221
|
+
console.log(ad.suggestion.title);
|
|
222
|
+
console.log(ad.suggestion.body);
|
|
223
|
+
console.log(`→ ${ad.suggestion.cta}\n`);
|
|
263
224
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
225
|
+
// 5. Track impression (for billing)
|
|
226
|
+
await client.trackImpression({
|
|
227
|
+
agent_id: 'your_agent_id',
|
|
228
|
+
request_id: decision.request_id,
|
|
229
|
+
decision_id: decision.decision_id,
|
|
230
|
+
unit_id: ad.unit_id,
|
|
231
|
+
tracking_token: ad.tracking.token
|
|
232
|
+
});
|
|
268
233
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
272
|
-
request_id: response.request_id,
|
|
273
|
-
decision_id: response.decision_id,
|
|
274
|
-
unit_id: unit.unit_id,
|
|
275
|
-
tracking_token: unit.tracking.token,
|
|
276
|
-
metadata: { surface: 'chat_response' },
|
|
277
|
-
});
|
|
234
|
+
// 6. Track click when user clicks (you earn money!)
|
|
235
|
+
// await client.trackClick({ ... });
|
|
278
236
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
decision_id: response.decision_id,
|
|
284
|
-
unit_id: unit.unit_id,
|
|
285
|
-
tracking_token: unit.tracking.token,
|
|
286
|
-
href: unit.suggestion.action_url,
|
|
287
|
-
});
|
|
237
|
+
return ad;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return null; // No ads available
|
|
288
241
|
}
|
|
242
|
+
|
|
243
|
+
// Example usage
|
|
244
|
+
await showRelevantAd("I need car insurance for my Honda");
|
|
245
|
+
await showRelevantAd("I need a divorce lawyer in California");
|
|
289
246
|
```
|
|
290
247
|
|
|
291
|
-
|
|
248
|
+
---
|
|
292
249
|
|
|
293
|
-
|
|
250
|
+
## API Reference
|
|
294
251
|
|
|
295
|
-
|
|
252
|
+
### Client Methods
|
|
296
253
|
|
|
254
|
+
**`client.decide(request)`** - Get ads (convenience method)
|
|
297
255
|
```typescript
|
|
298
|
-
const
|
|
299
|
-
request_id:
|
|
300
|
-
agent_id:
|
|
301
|
-
placement: {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
256
|
+
const decision = await client.decide({
|
|
257
|
+
request_id: crypto.randomUUID(),
|
|
258
|
+
agent_id: 'your_agent_id',
|
|
259
|
+
placement: { type: 'sponsored_suggestion' },
|
|
260
|
+
opportunity: {
|
|
261
|
+
intent: { taxonomy: 'insurance.auto.full_coverage.quote' },
|
|
262
|
+
context: { country: 'US', language: 'en', platform: 'web' }
|
|
263
|
+
}
|
|
306
264
|
});
|
|
307
265
|
```
|
|
308
266
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
Returns the full response including status, ttl_ms, and all units.
|
|
312
|
-
|
|
267
|
+
**`client.decideRaw(request)`** - Get full response with metadata
|
|
313
268
|
```typescript
|
|
314
|
-
const response = await client.decideRaw(
|
|
315
|
-
|
|
316
|
-
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
317
|
-
placement: { type: 'sponsored_suggestion', surface: 'chat_response' },
|
|
318
|
-
opportunity,
|
|
319
|
-
}, {
|
|
320
|
-
idempotencyKey: 'optional-idempotency-key',
|
|
321
|
-
});
|
|
269
|
+
const response = await client.decideRaw(request);
|
|
270
|
+
// Returns: { status, request_id, decision_id, units[], ttl_ms }
|
|
322
271
|
```
|
|
323
272
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
Convenience method to track when a unit is rendered.
|
|
327
|
-
|
|
273
|
+
**`client.trackImpression(params)`** - Track when ad is shown
|
|
328
274
|
```typescript
|
|
329
275
|
await client.trackImpression({
|
|
330
|
-
agent_id:
|
|
276
|
+
agent_id: 'your_agent_id',
|
|
331
277
|
request_id: 'req_123',
|
|
332
278
|
decision_id: 'dec_456',
|
|
333
279
|
unit_id: 'unit_789',
|
|
334
|
-
tracking_token: 'trk_abc'
|
|
335
|
-
metadata: { surface: 'chat_response' },
|
|
280
|
+
tracking_token: 'trk_abc'
|
|
336
281
|
});
|
|
337
282
|
```
|
|
338
283
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
Convenience method to track when a user clicks a unit.
|
|
342
|
-
|
|
284
|
+
**`client.trackClick(params)`** - Track when ad is clicked (you earn $)
|
|
343
285
|
```typescript
|
|
344
286
|
await client.trackClick({
|
|
345
|
-
agent_id:
|
|
287
|
+
agent_id: 'your_agent_id',
|
|
346
288
|
request_id: 'req_123',
|
|
347
289
|
decision_id: 'dec_456',
|
|
348
290
|
unit_id: 'unit_789',
|
|
349
291
|
tracking_token: 'trk_abc',
|
|
350
|
-
href: 'https://
|
|
292
|
+
href: 'https://advertiser.com'
|
|
351
293
|
});
|
|
352
294
|
```
|
|
353
295
|
|
|
354
|
-
###
|
|
296
|
+
### Helper Functions
|
|
355
297
|
|
|
356
|
-
|
|
298
|
+
- `buildTaxonomy(vertical, category, subcategory, intent?)` - Build taxonomy string
|
|
299
|
+
- `detectIntent(query)` - Auto-detect user intent from query
|
|
300
|
+
- `suggestTaxonomies(query)` - Get relevant taxonomy suggestions
|
|
301
|
+
- `isValidTaxonomy(taxonomy)` - Validate taxonomy format
|
|
302
|
+
- `parseTaxonomy(taxonomy)` - Parse taxonomy into components
|
|
303
|
+
- `getBaseTaxonomy(taxonomy)` - Get taxonomy without intent
|
|
304
|
+
- `matchesTaxonomy(tax1, tax2)` - Check if taxonomies match
|
|
305
|
+
- `getVertical(taxonomy)` - Extract industry vertical
|
|
357
306
|
|
|
358
|
-
|
|
359
|
-
await client.track({
|
|
360
|
-
event_id: generateUUID(),
|
|
361
|
-
occurred_at: new Date().toISOString(),
|
|
362
|
-
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
363
|
-
request_id: 'req_123',
|
|
364
|
-
decision_id: 'dec_456',
|
|
365
|
-
unit_id: 'unit_789',
|
|
366
|
-
event_type: 'impression',
|
|
367
|
-
tracking_token: 'trk_abc',
|
|
368
|
-
});
|
|
369
|
-
```
|
|
307
|
+
### Security Helpers
|
|
370
308
|
|
|
371
|
-
|
|
309
|
+
- `escapeHTML(text)` - Escape HTML to prevent XSS
|
|
310
|
+
- `sanitizeURL(url)` - Validate and sanitize URLs
|
|
372
311
|
|
|
373
|
-
|
|
312
|
+
**Always sanitize ad content before rendering!**
|
|
374
313
|
|
|
375
|
-
|
|
376
|
-
const policy = await client.getPolicy();
|
|
377
|
-
console.log(policy.defaults.max_units_per_response);
|
|
378
|
-
console.log(policy.disclosure.label);
|
|
379
|
-
```
|
|
314
|
+
---
|
|
380
315
|
|
|
381
|
-
|
|
316
|
+
## Testing
|
|
382
317
|
|
|
383
|
-
|
|
318
|
+
### Mock Client (No API calls)
|
|
384
319
|
|
|
385
320
|
```typescript
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
321
|
+
import { MockAttentionMarketClient } from '@the_ro_show/agent-ads-sdk';
|
|
322
|
+
|
|
323
|
+
const client = new MockAttentionMarketClient({
|
|
324
|
+
fillRate: 1.0, // Always return ads
|
|
325
|
+
latencyMs: 100, // Simulate API latency
|
|
326
|
+
verbose: true // Log activity
|
|
391
327
|
});
|
|
392
328
|
|
|
393
|
-
|
|
394
|
-
|
|
329
|
+
// Works exactly like real client, but returns mock data
|
|
330
|
+
const decision = await client.decide(request);
|
|
395
331
|
```
|
|
396
332
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
### `createOpportunity(params): Opportunity`
|
|
400
|
-
|
|
401
|
-
Build a valid Opportunity object with safe defaults.
|
|
333
|
+
### Test Taxonomies
|
|
402
334
|
|
|
335
|
+
Use your test key with real API:
|
|
403
336
|
```typescript
|
|
404
|
-
const
|
|
405
|
-
//
|
|
406
|
-
taxonomy: 'local_services.movers.quote',
|
|
407
|
-
country: 'US',
|
|
408
|
-
language: 'en',
|
|
409
|
-
platform: 'web',
|
|
410
|
-
|
|
411
|
-
// Optional
|
|
412
|
-
query: 'Find movers in Brooklyn',
|
|
413
|
-
region: 'NY',
|
|
414
|
-
city: 'New York',
|
|
415
|
-
|
|
416
|
-
// Optional overrides (with defaults shown)
|
|
417
|
-
constraints: {
|
|
418
|
-
max_units: 1,
|
|
419
|
-
allowed_unit_types: ['sponsored_suggestion'],
|
|
420
|
-
blocked_categories: ['adult'],
|
|
421
|
-
},
|
|
422
|
-
privacy: {
|
|
423
|
-
data_policy: 'coarse_only',
|
|
424
|
-
},
|
|
337
|
+
const client = new AttentionMarketClient({
|
|
338
|
+
apiKey: process.env.ATTENTIONMARKET_TEST_KEY // am_test_...
|
|
425
339
|
});
|
|
426
340
|
```
|
|
427
341
|
|
|
428
|
-
|
|
342
|
+
---
|
|
429
343
|
|
|
430
|
-
|
|
344
|
+
## Security
|
|
431
345
|
|
|
432
|
-
|
|
433
|
-
import { createImpressionEvent } from '@the_ro_show/agent-ads-sdk';
|
|
346
|
+
### ⚠️ CRITICAL: Server-Side Only
|
|
434
347
|
|
|
435
|
-
|
|
436
|
-
agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
|
|
437
|
-
request_id: 'req_123',
|
|
438
|
-
decision_id: 'dec_456',
|
|
439
|
-
unit_id: 'unit_789',
|
|
440
|
-
tracking_token: 'trk_abc',
|
|
441
|
-
occurred_at: new Date().toISOString(), // optional, auto-generated
|
|
442
|
-
metadata: { surface: 'chat_response' }, // optional
|
|
443
|
-
});
|
|
348
|
+
**Never use this SDK in browsers or mobile apps.** Your API key has full access to your account.
|
|
444
349
|
|
|
445
|
-
|
|
446
|
-
|
|
350
|
+
✅ **Safe:** Node.js, serverless functions, server-side rendering
|
|
351
|
+
❌ **Unsafe:** Browser JavaScript, React/Vue components, mobile apps
|
|
447
352
|
|
|
448
|
-
###
|
|
353
|
+
### Sanitize Ad Content
|
|
449
354
|
|
|
450
|
-
|
|
355
|
+
Always escape ad content before rendering:
|
|
451
356
|
|
|
452
357
|
```typescript
|
|
453
|
-
import {
|
|
358
|
+
import { escapeHTML, sanitizeURL } from '@the_ro_show/agent-ads-sdk';
|
|
454
359
|
|
|
455
|
-
const
|
|
456
|
-
|
|
457
|
-
request_id: 'req_123',
|
|
458
|
-
decision_id: 'dec_456',
|
|
459
|
-
unit_id: 'unit_789',
|
|
460
|
-
tracking_token: 'trk_abc',
|
|
461
|
-
href: 'https://example.com',
|
|
462
|
-
occurred_at: new Date().toISOString(), // optional, auto-generated
|
|
463
|
-
});
|
|
360
|
+
const safeTitle = escapeHTML(ad.suggestion.title);
|
|
361
|
+
const safeURL = sanitizeURL(ad.suggestion.action_url);
|
|
464
362
|
|
|
465
|
-
|
|
363
|
+
if (safeURL) {
|
|
364
|
+
element.innerHTML = `<a href="${safeURL}">${safeTitle}</a>`;
|
|
365
|
+
}
|
|
466
366
|
```
|
|
467
367
|
|
|
468
|
-
|
|
368
|
+
**See [SECURITY.md](./SECURITY.md) for complete guidelines.**
|
|
469
369
|
|
|
470
|
-
|
|
370
|
+
---
|
|
471
371
|
|
|
472
|
-
|
|
473
|
-
import { generateUUID } from '@the_ro_show/agent-ads-sdk';
|
|
372
|
+
## Examples
|
|
474
373
|
|
|
475
|
-
|
|
476
|
-
|
|
374
|
+
**Minimal integrations** (< 80 lines):
|
|
375
|
+
- [Claude Tool Use](./examples/claude-tool-use-minimal.ts)
|
|
376
|
+
- [OpenAI Function Calling](./examples/openai-function-calling-minimal.ts)
|
|
377
|
+
- [Google Gemini](./examples/gemini-function-calling-minimal.ts)
|
|
477
378
|
|
|
478
|
-
|
|
379
|
+
**Full integrations** (production-ready):
|
|
380
|
+
- [Claude Complete](./examples/claude-tool-use-full.ts)
|
|
381
|
+
- [OpenAI Complete](./examples/openai-function-calling-full.ts)
|
|
382
|
+
- [Safe Web Rendering](./examples/safe-web-rendering.ts)
|
|
479
383
|
|
|
480
|
-
|
|
384
|
+
Run any example:
|
|
385
|
+
```bash
|
|
386
|
+
npx tsx examples/claude-tool-use-minimal.ts
|
|
387
|
+
```
|
|
481
388
|
|
|
482
|
-
|
|
483
|
-
import { escapeHTML } from '@the_ro_show/agent-ads-sdk';
|
|
389
|
+
---
|
|
484
390
|
|
|
485
|
-
|
|
486
|
-
element.innerHTML = safeTitle; // Safe from XSS
|
|
487
|
-
```
|
|
391
|
+
## Documentation
|
|
488
392
|
|
|
489
|
-
|
|
393
|
+
- **[Simple Integration Guide](./SIMPLE_INTEGRATION_GUIDE.md)** - Step-by-step for beginners
|
|
394
|
+
- **[Taxonomy System](./TAXONOMY_SYSTEM.md)** - Complete taxonomy reference
|
|
395
|
+
- **[Migration Guide](./TAXONOMY_MIGRATION_GUIDE.md)** - Upgrading from older versions
|
|
396
|
+
- **[Security Guide](./SECURITY.md)** - Security best practices
|
|
397
|
+
- **[Advertiser Guide](./ADVERTISER_ONBOARDING_GUIDE.md)** - For advertisers
|
|
490
398
|
|
|
491
|
-
|
|
399
|
+
---
|
|
492
400
|
|
|
493
|
-
|
|
401
|
+
## Features
|
|
494
402
|
|
|
495
|
-
|
|
496
|
-
|
|
403
|
+
- ✅ **Hierarchical matching** - Advertisers target broadly, agents match specifically
|
|
404
|
+
- ✅ **Auto-intent detection** - Automatically detect research vs quote vs apply
|
|
405
|
+
- ✅ **50+ high-value taxonomies** - Insurance, legal, finance, B2B SaaS, and more
|
|
406
|
+
- ✅ **TypeScript support** - Full type definitions included
|
|
407
|
+
- ✅ **Automatic retries** - Exponential backoff for failed requests
|
|
408
|
+
- ✅ **Mock client** - Test without API calls
|
|
409
|
+
- ✅ **Security helpers** - XSS protection, URL sanitization
|
|
410
|
+
- ✅ **Zero dependencies** - No external runtime dependencies
|
|
497
411
|
|
|
498
|
-
|
|
412
|
+
---
|
|
499
413
|
|
|
500
|
-
|
|
501
|
-
window.open(safeURL, '_blank');
|
|
502
|
-
} else {
|
|
503
|
-
console.error('Dangerous URL blocked');
|
|
504
|
-
}
|
|
505
|
-
```
|
|
414
|
+
## Pricing
|
|
506
415
|
|
|
507
|
-
**
|
|
416
|
+
**Free to use.** You earn money when users click ads:
|
|
508
417
|
|
|
509
|
-
**
|
|
510
|
-
-
|
|
511
|
-
-
|
|
512
|
-
-
|
|
418
|
+
- **Insurance:** $20-54 per click
|
|
419
|
+
- **Legal:** $50-150 per click
|
|
420
|
+
- **Financial:** $15-50 per click
|
|
421
|
+
- **B2B SaaS:** $10-100 per click
|
|
422
|
+
- **Home Services:** $5-30 per click
|
|
513
423
|
|
|
514
|
-
|
|
424
|
+
**You keep 70% of revenue.** Paid monthly via Stripe.
|
|
515
425
|
|
|
516
|
-
|
|
517
|
-
- ✅ Automatic retries with exponential backoff
|
|
518
|
-
- ✅ Configurable timeouts (default 4000ms)
|
|
519
|
-
- ✅ Idempotency support
|
|
520
|
-
- ✅ Discriminated union types for type-safe ad units
|
|
521
|
-
- ✅ Helper functions for common operations
|
|
522
|
-
- ✅ No external runtime dependencies (Node.js 18+)
|
|
426
|
+
---
|
|
523
427
|
|
|
524
428
|
## Requirements
|
|
525
429
|
|
|
526
430
|
- Node.js 18 or higher
|
|
527
|
-
- TypeScript 5.3
|
|
431
|
+
- TypeScript 5.3+ (for development)
|
|
528
432
|
|
|
529
|
-
|
|
433
|
+
---
|
|
530
434
|
|
|
531
|
-
|
|
435
|
+
## Support
|
|
532
436
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
} catch (error) {
|
|
539
|
-
if (error instanceof APIRequestError) {
|
|
540
|
-
console.error(`API Error [${error.statusCode}]: ${error.errorCode}`);
|
|
541
|
-
console.error(`Message: ${error.message}`);
|
|
542
|
-
console.error(`Request ID: ${error.requestId}`);
|
|
543
|
-
} else if (error instanceof TimeoutError) {
|
|
544
|
-
console.error('Request timed out');
|
|
545
|
-
} else if (error instanceof NetworkError) {
|
|
546
|
-
console.error('Network error:', error.message);
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
```
|
|
437
|
+
- **Issues:** [GitHub Issues](https://github.com/rtrivedi/agent-ads-sdk/issues)
|
|
438
|
+
- **Docs:** [SIMPLE_INTEGRATION_GUIDE.md](./SIMPLE_INTEGRATION_GUIDE.md)
|
|
439
|
+
- **Email:** support@attentionmarket.com
|
|
440
|
+
|
|
441
|
+
---
|
|
550
442
|
|
|
551
443
|
## License
|
|
552
444
|
|
|
553
445
|
MIT
|
|
446
|
+
|
|
447
|
+
---
|
|
448
|
+
|
|
449
|
+
## Changelog
|
|
450
|
+
|
|
451
|
+
### v0.4.0 (2026-02-03)
|
|
452
|
+
|
|
453
|
+
**New Features:**
|
|
454
|
+
- ✨ Hierarchical taxonomy matching (3x more inventory)
|
|
455
|
+
- ✨ `buildTaxonomy()` helper function
|
|
456
|
+
- ✨ `detectIntent()` auto-intent detection
|
|
457
|
+
- ✨ `suggestTaxonomies()` get relevant taxonomies
|
|
458
|
+
- ✨ `isValidTaxonomy()` and `parseTaxonomy()` validators
|
|
459
|
+
- ✨ 50 Phase 1 high-value taxonomies (insurance, legal, finance, etc.)
|
|
460
|
+
|
|
461
|
+
**Improvements:**
|
|
462
|
+
- 🎯 Relevance scoring (1.0 → 0.9 → 0.7 → 0.5)
|
|
463
|
+
- 🔄 Backward compatibility for old taxonomies (90-day migration window)
|
|
464
|
+
- 📚 Complete taxonomy documentation
|
|
465
|
+
|
|
466
|
+
**Breaking Changes:**
|
|
467
|
+
- None! Fully backward compatible.
|
|
468
|
+
|
|
469
|
+
### v0.2.1
|
|
470
|
+
|
|
471
|
+
- Initial public release
|
|
472
|
+
- Multi-ad response support
|
|
473
|
+
- Mock client for testing
|
|
474
|
+
- Security helpers (escapeHTML, sanitizeURL)
|