@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 CHANGED
@@ -1,553 +1,465 @@
1
1
  # AttentionMarket Agent Ads SDK
2
2
 
3
- TypeScript SDK for integrating agent-native sponsored units (Sponsored Suggestions and Sponsored Tools) into AI agents.
3
+ TypeScript SDK for monetizing AI agents with relevant sponsored content. Earn $5-50 per click.
4
4
 
5
- ## 🚀 New to this? Start Here
5
+ ## Quick Start
6
6
 
7
- **→ [Simple Integration Guide](./SIMPLE_INTEGRATION_GUIDE.md)** - Step-by-step guide for Clawdbot/Moltbot developers
7
+ ### 1. Get Your API Key
8
8
 
9
- This README contains the full API reference. If you're just getting started, the Simple Integration Guide is much easier to follow!
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
- ## Installation
15
+ ### 2. Install
14
16
 
15
17
  ```bash
16
18
  npm install @the_ro_show/agent-ads-sdk
17
19
  ```
18
20
 
19
- ## Configuration
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, createOpportunity, generateUUID } from '@the_ro_show/agent-ads-sdk';
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 opportunity = createOpportunity({
38
- taxonomy: 'local_services.movers.quote',
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
- const unit = await client.decide({
46
- request_id: generateUUID(),
47
- agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
48
- placement: { type: 'sponsored_suggestion', surface: 'chat_response' },
49
- opportunity,
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 (unit && unit.unit_type === 'sponsored_suggestion') {
53
- console.log(`[${unit.disclosure.label}] ${unit.disclosure.sponsor_name}`);
54
- console.log(unit.suggestion.title);
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
- ## Security Best Practices
67
-
68
- 🔴 **CRITICAL SECURITY REQUIREMENTS**
52
+ **That's it!** Start earning from relevant ads.
69
53
 
70
- ### 1. Server-Side Only
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
- **Safe:** Node.js, serverless functions, server-side rendering
75
- ❌ **Unsafe:** Browser JavaScript, mobile apps without backend proxy
56
+ ## 🆕 What's New in v0.4.0
76
57
 
77
- ### 2. Sanitize Ad Content Before Display
58
+ ### Hierarchical Taxonomy Matching
78
59
 
79
- Ad content can contain malicious HTML/JavaScript. **Always sanitize** before rendering in HTML:
60
+ Target broadly, match specifically:
80
61
 
81
62
  ```typescript
82
- import { escapeHTML, sanitizeURL } from '@the_ro_show/agent-ads-sdk';
63
+ // Advertiser targets: "insurance.auto"
64
+ // Your agent requests: "insurance.auto.full_coverage.quote"
65
+ // ✅ Matches! (0.7 relevance score)
83
66
 
84
- // SAFE: Sanitize content
85
- const safeTitle = escapeHTML(unit.suggestion.title);
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
- if (safeURL) {
90
- element.innerHTML = `<a href="${safeURL}">${safeTitle}</a>`;
91
- }
70
+ // Your agent requests: "insurance.home.flood.quote"
71
+ // No match (different category)
92
72
  ```
93
73
 
94
- ```typescript
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
- ### 3. Validate URLs
100
-
101
- Always validate `action_url` before using:
76
+ ### New Helper Functions
102
77
 
78
+ **Auto-detect user intent:**
103
79
  ```typescript
104
- const safeURL = sanitizeURL(unit.suggestion.action_url);
80
+ import { detectIntent } from '@the_ro_show/agent-ads-sdk';
105
81
 
106
- if (!safeURL) {
107
- console.error('Dangerous URL blocked');
108
- return; // Don't render the ad
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
- Blocks dangerous protocols: `javascript:`, `data:`, `file:`
113
-
114
- ### 4. See Complete Guidelines
88
+ **Build taxonomies easily:**
89
+ ```typescript
90
+ import { buildTaxonomy } from '@the_ro_show/agent-ads-sdk';
115
91
 
116
- 📖 **[Read SECURITY.md](./SECURITY.md)** for comprehensive security guidelines including:
117
- - XSS prevention examples
118
- - Phishing protection
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
- ## Testing Without Advertiser Data
96
+ **Get taxonomy suggestions:**
97
+ ```typescript
98
+ import { suggestTaxonomies } from '@the_ro_show/agent-ads-sdk';
124
99
 
125
- Use `MockAttentionMarketClient` to test your integration without needing real ad campaigns.
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 { MockAttentionMarketClient, createOpportunity, generateUUID } from '@the_ro_show/agent-ads-sdk';
106
+ import { isValidTaxonomy, parseTaxonomy } from '@the_ro_show/agent-ads-sdk';
129
107
 
130
- // Use mock client during development
131
- const client = new MockAttentionMarketClient({
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 unit = await client.decide({
146
- request_id: generateUUID(),
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
- **Available mock taxonomies:**
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
- **Add custom mock ads:**
117
+ ## Common Taxonomies
167
118
 
119
+ ### Insurance ($20-54 CPC)
168
120
  ```typescript
169
- client.addMockUnit('your.custom.taxonomy', {
170
- unit_id: 'unit_custom_001',
171
- unit_type: 'sponsored_suggestion',
172
- disclosure: { label: 'Sponsored', sponsor_name: 'Your Sponsor' },
173
- tracking: { token: 'trk_test', impression_url: '...', click_url: '...' },
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
- **Run the full test suite:**
184
-
185
- ```bash
186
- npx tsx examples/test-with-mocks.ts
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
- **Switch to production:**
190
-
137
+ ### Financial Services ($15-50 CPC)
191
138
  ```typescript
192
- const client = process.env.NODE_ENV === 'production'
193
- ? new AttentionMarketClient({ apiKey: process.env.ATTENTIONMARKET_API_KEY })
194
- : new MockAttentionMarketClient();
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
- ## Agent Integration Examples
198
-
199
- ### Minimal Examples (< 80 lines)
200
-
201
- Start here for a quick overview:
202
-
203
- - **[Claude](./examples/claude-tool-use-minimal.ts)** - Minimal tool use integration
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
- For production integrations:
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
- - **[Claude (Anthropic)](./examples/claude-tool-use-full.ts)** - Complete tool use pattern with schemas and tracking
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
- Run any example with:
219
- ```bash
220
- npx tsx examples/claude-tool-use-minimal.ts
221
- npx tsx examples/safe-web-rendering.ts
222
- ```
163
+ ---
223
164
 
224
- ## Full Example with Raw Response
165
+ ## Complete Example
225
166
 
226
167
  ```typescript
227
168
  import {
228
169
  AttentionMarketClient,
229
- createOpportunity,
230
- generateUUID,
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
- // Build opportunity
238
- const opportunity = createOpportunity({
239
- taxonomy: 'local_services.movers.quote',
240
- country: 'US',
241
- language: 'en',
242
- platform: 'web',
243
- query: 'Find movers in Brooklyn',
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
- // Get full response (includes status, ttl_ms, all units)
247
- const response = await client.decideRaw({
248
- request_id: generateUUID(),
249
- agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
250
- placement: {
251
- type: 'sponsored_suggestion',
252
- surface: 'chat_response',
253
- },
254
- opportunity,
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
- if (response.status === 'filled') {
258
- // Access all units and metadata
259
- console.log(`TTL: ${response.ttl_ms}ms`);
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
- const unit = response.units[0];
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
- // Render unit
265
- if (unit && unit.unit_type === 'sponsored_suggestion') {
266
- console.log(unit.suggestion.title);
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
- // Track impression after rendering
270
- await client.trackImpression({
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
- // Track click when user clicks
280
- await client.trackClick({
281
- agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
282
- request_id: response.request_id,
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
- ## API Methods
239
+ ---
292
240
 
293
- ### `decide(request, options?): Promise<AdUnit | null>`
241
+ ## API Reference
294
242
 
295
- Convenience method that returns the first ad unit or `null` if no fill.
243
+ ### Client Methods
296
244
 
245
+ **`client.decide(request)`** - Get ads (convenience method)
297
246
  ```typescript
298
- const unit = await client.decide({
299
- request_id: generateUUID(),
300
- agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
301
- placement: {
302
- type: 'sponsored_suggestion',
303
- surface: 'chat_response',
304
- },
305
- opportunity,
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
- ### `decideRaw(request, options?): Promise<DecideResponse>`
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
- request_id: generateUUID(),
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
- ### `trackImpression(params): Promise<EventIngestResponse>`
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: process.env.ATTENTIONMARKET_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
- ### `trackClick(params): Promise<EventIngestResponse>`
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: process.env.ATTENTIONMARKET_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://example.com/action',
283
+ href: 'https://advertiser.com'
351
284
  });
352
285
  ```
353
286
 
354
- ### `track(event): Promise<EventIngestResponse>`
287
+ ### Helper Functions
355
288
 
356
- Low-level method to track any event type.
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
- ```typescript
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
- ### `getPolicy(): Promise<PolicyResponse>`
300
+ - `escapeHTML(text)` - Escape HTML to prevent XSS
301
+ - `sanitizeURL(url)` - Validate and sanitize URLs
372
302
 
373
- Fetch policy constraints and formatting requirements.
303
+ **Always sanitize ad content before rendering!**
374
304
 
375
- ```typescript
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
- ### `signupAgent(request, options?): Promise<AgentSignupResponse>` (static)
307
+ ## Testing
382
308
 
383
- Register a new agent (unauthenticated endpoint).
309
+ ### Mock Client (No API calls)
384
310
 
385
311
  ```typescript
386
- const signup = await AttentionMarketClient.signupAgent({
387
- owner_email: 'owner@company.com',
388
- agent_name: 'My Agent',
389
- sdk: 'typescript',
390
- environment: 'test',
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
- console.log(signup.agent_id);
394
- console.log(signup.api_key);
320
+ // Works exactly like real client, but returns mock data
321
+ const decision = await client.decide(request);
395
322
  ```
396
323
 
397
- ## Helper Functions
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 opportunity = createOpportunity({
405
- // Required
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
- ### `createImpressionEvent(params): EventIngestRequest`
333
+ ---
429
334
 
430
- Build an impression event payload.
335
+ ## Security
431
336
 
432
- ```typescript
433
- import { createImpressionEvent } from '@the_ro_show/agent-ads-sdk';
337
+ ### ⚠️ CRITICAL: Server-Side Only
434
338
 
435
- const event = createImpressionEvent({
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
- await client.track(event);
446
- ```
341
+ **Safe:** Node.js, serverless functions, server-side rendering
342
+ ❌ **Unsafe:** Browser JavaScript, React/Vue components, mobile apps
447
343
 
448
- ### `createClickEvent(params): EventIngestRequest`
344
+ ### Sanitize Ad Content
449
345
 
450
- Build a click event payload.
346
+ Always escape ad content before rendering:
451
347
 
452
348
  ```typescript
453
- import { createClickEvent } from '@the_ro_show/agent-ads-sdk';
349
+ import { escapeHTML, sanitizeURL } from '@the_ro_show/agent-ads-sdk';
454
350
 
455
- const event = createClickEvent({
456
- agent_id: process.env.ATTENTIONMARKET_AGENT_ID,
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
- await client.track(event);
354
+ if (safeURL) {
355
+ element.innerHTML = `<a href="${safeURL}">${safeTitle}</a>`;
356
+ }
466
357
  ```
467
358
 
468
- ### `generateUUID(): string`
359
+ **See [SECURITY.md](./SECURITY.md) for complete guidelines.**
469
360
 
470
- Generate a UUID v4 for request_id, event_id, etc.
361
+ ---
471
362
 
472
- ```typescript
473
- import { generateUUID } from '@the_ro_show/agent-ads-sdk';
363
+ ## Examples
474
364
 
475
- const requestId = generateUUID();
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
- ### `escapeHTML(text): string`
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
- Escape HTML special characters to prevent XSS attacks.
375
+ Run any example:
376
+ ```bash
377
+ npx tsx examples/claude-tool-use-minimal.ts
378
+ ```
481
379
 
482
- ```typescript
483
- import { escapeHTML } from '@the_ro_show/agent-ads-sdk';
380
+ ---
484
381
 
485
- const safeTitle = escapeHTML(unit.suggestion.title);
486
- element.innerHTML = safeTitle; // Safe from XSS
487
- ```
382
+ ## Documentation
488
383
 
489
- Escapes: `&`, `<`, `>`, `"`, `'`, `/`
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
- ### `sanitizeURL(url, options?): string | null`
390
+ ---
492
391
 
493
- Validate and sanitize URLs to prevent XSS and phishing attacks.
392
+ ## Features
494
393
 
495
- ```typescript
496
- import { sanitizeURL } from '@the_ro_show/agent-ads-sdk';
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
- const safeURL = sanitizeURL(unit.suggestion.action_url);
403
+ ---
499
404
 
500
- if (safeURL) {
501
- window.open(safeURL, '_blank');
502
- } else {
503
- console.error('Dangerous URL blocked');
504
- }
505
- ```
405
+ ## Pricing
506
406
 
507
- **Blocked protocols:** `javascript:`, `data:`, `file:`, `vbscript:`
407
+ **Free to use.** You earn money when users click ads:
508
408
 
509
- **Options:**
510
- - `allowHttp: boolean` - Allow HTTP URLs (default: false, HTTPS only)
511
- - `allowTel: boolean` - Allow tel: links (default: true)
512
- - `allowMailto: boolean` - Allow mailto: links (default: true)
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
- ## Features
415
+ **You keep 70% of revenue.** Paid monthly via Stripe.
515
416
 
516
- - ✅ TypeScript support with full type definitions
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 or higher (for development)
422
+ - TypeScript 5.3+ (for development)
528
423
 
529
- ## Error Handling
424
+ ---
530
425
 
531
- The SDK throws typed errors that include full API context:
426
+ ## Support
532
427
 
533
- ```typescript
534
- import { APIRequestError, NetworkError, TimeoutError } from '@the_ro_show/agent-ads-sdk';
535
-
536
- try {
537
- const unit = await client.decide(request);
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)