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