@the_ro_show/agent-ads-sdk 0.11.0 → 0.13.0

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
@@ -418,6 +418,150 @@ curl -X POST https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/feedback \
418
418
 
419
419
  ---
420
420
 
421
+ ## 🎛️ Developer Controls (v0.12.0+)
422
+
423
+ Take control of what ads appear in your app with quality, category, and advertiser filters.
424
+
425
+ ### Quality Score Filter
426
+
427
+ Only show ads that meet your quality standards:
428
+
429
+ ```typescript
430
+ const ad = await client.decideFromContext({
431
+ userMessage: "I need car insurance",
432
+ minQualityScore: 0.8 // Only ads with 0.8+ quality
433
+ });
434
+ ```
435
+
436
+ **Use cases:**
437
+ - **Premium apps**: Set 0.9+ for best-in-class ads only
438
+ - **General apps**: Set 0.7+ for good balance
439
+ - **High-volume apps**: Set 0.5+ to maximize fill rate
440
+
441
+ ### Category Controls (IAB Taxonomy 3.0)
442
+
443
+ Filter ads using **IAB Content Taxonomy 3.0** - the industry-standard category system used by Google Ads, Microsoft Ads, and all major ad platforms.
444
+
445
+ **704 categories** across 38 top-level categories with 4-tier hierarchy.
446
+
447
+ #### Discover Available Categories
448
+
449
+ ```typescript
450
+ // Get all 38 top-level categories
451
+ const tier1 = await client.getCategories({ tier: 1 });
452
+ tier1.categories.forEach(cat => {
453
+ console.log(`${cat.id}: ${cat.name}`);
454
+ });
455
+ // Output: 1: Automotive, 31: Insurance, 150: Attractions, etc.
456
+
457
+ // Get all subcategories of "Automotive" (ID: 1)
458
+ const automotive = await client.getCategories({ parent_id: 1 });
459
+ // Returns: Auto Insurance (31), Auto Repair (34), Auto Buying (30), etc.
460
+
461
+ // Search for insurance-related categories
462
+ const insurance = await client.getCategories({ search: 'insurance' });
463
+ insurance.categories.forEach(cat => {
464
+ console.log(cat.full_path);
465
+ });
466
+ // Output: "Automotive > Auto Insurance", "Personal Finance > Insurance", etc.
467
+ ```
468
+
469
+ #### Filter by Category
470
+
471
+ Use IAB category IDs for precise control:
472
+
473
+ ```typescript
474
+ // Insurance app: Only show insurance ads (by IAB ID)
475
+ const ad = await client.decideFromContext({
476
+ userMessage: "I need car insurance",
477
+ allowedCategories: [31] // 31 = Auto Insurance
478
+ });
479
+
480
+ // Block entire "Sensitive Topics" tree (IAB ID: 601)
481
+ // This blocks all gambling, adult content, controversial topics, etc.
482
+ const ad = await client.decideFromContext({
483
+ userMessage: "Help me with something",
484
+ blockedCategories: [601] // Blocks parent + all children
485
+ });
486
+
487
+ // Wedding planner: Allow wedding + photography + food
488
+ const ad = await client.decideFromContext({
489
+ userMessage: "Help me plan my wedding",
490
+ allowedCategories: [
491
+ 603, // Weddings (Personal Celebrations)
492
+ 162, // Photography (Hobbies & Interests)
493
+ 190 // Restaurants (Food & Drink)
494
+ ]
495
+ });
496
+ ```
497
+
498
+ **Parent-Child Relationships:**
499
+ - Blocking a parent category blocks ALL child categories automatically
500
+ - Example: Blocking `1` (Automotive) blocks Auto Insurance, Auto Repair, etc.
501
+ - Great for compliance: Block `601` (Sensitive Topics) to block gambling, adult, controversial in one go
502
+
503
+ **Note:** If `allowedCategories` is set, `blockedCategories` is ignored.
504
+
505
+ ### Advertiser Blocklist
506
+
507
+ Block specific advertisers based on user feedback:
508
+
509
+ ```typescript
510
+ const ad = await client.decideFromContext({
511
+ userMessage: "I need legal help",
512
+ blockedAdvertisers: ['adv_abc123', 'adv_xyz789']
513
+ });
514
+ ```
515
+
516
+ Get advertiser IDs from previous ad responses.
517
+
518
+ ### Combined Controls
519
+
520
+ Mix and match for precise control:
521
+
522
+ ```typescript
523
+ const ad = await client.decideFromContext({
524
+ userMessage: "I need car insurance",
525
+ minQualityScore: 0.8, // High quality only
526
+ blockedCategories: ['crypto'], // No crypto ads
527
+ allowedCategories: ['insurance', 'finance'] // Relevant only
528
+ });
529
+ ```
530
+
531
+ ### HTTP Example
532
+
533
+ ```bash
534
+ curl -X POST https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/decide \
535
+ -H "X-AM-API-Key: am_live_YOUR_KEY" \
536
+ -H "Content-Type: application/json" \
537
+ -d '{
538
+ "context": "I need car insurance",
539
+ "minQualityScore": 0.8,
540
+ "blockedCategories": ["crypto", "gambling"]
541
+ }'
542
+ ```
543
+
544
+ ### Best Practices
545
+
546
+ **Quality Scores:**
547
+ - Start with no filter, monitor what you get
548
+ - Gradually increase threshold if quality is lacking
549
+ - Higher thresholds = fewer ads but better quality
550
+
551
+ **Categories (IAB Taxonomy):**
552
+ - Use `getCategories()` to discover the full 704-category taxonomy
553
+ - Use `allowedCategories` for specialized apps (wedding planner = `[603]`, legal assistant = `[318]`)
554
+ - Use `blockedCategories` for compliance (kids apps = block `[601]` Sensitive Topics)
555
+ - Parent categories block all children automatically (block `[1]` Automotive = blocks all 40+ auto subcategories)
556
+ - Full taxonomy reference: https://github.com/InteractiveAdvertisingBureau/Taxonomies
557
+
558
+ **Advertiser Blocking:**
559
+ - Collect user feedback on specific ads
560
+ - Block advertisers with multiple complaints
561
+ - Use sparingly - too many blocks reduce fill rate
562
+
563
+ ---
564
+
421
565
  ## API Reference
422
566
 
423
567
  ### `POST /v1/decide`
package/dist/index.d.mts CHANGED
@@ -63,6 +63,39 @@ interface DecideFromContextRequest {
63
63
  language?: string;
64
64
  /** User's platform. Default: 'web' */
65
65
  platform?: 'web' | 'ios' | 'android' | 'desktop' | 'voice' | 'other';
66
+ /**
67
+ * Minimum quality score threshold (0.0 - 1.0).
68
+ * Only return ads with quality scores at or above this value.
69
+ * Higher values = better quality but lower fill rate.
70
+ *
71
+ * @example
72
+ * minQualityScore: 0.8 // Only show ads with 0.8+ quality
73
+ */
74
+ minQualityScore?: number;
75
+ /**
76
+ * Only show ads from these categories.
77
+ * If set, blockedCategories is ignored.
78
+ *
79
+ * @example
80
+ * allowedCategories: ['wedding', 'photography', 'venues']
81
+ */
82
+ allowedCategories?: string[];
83
+ /**
84
+ * Never show ads from these categories.
85
+ * Ignored if allowedCategories is set.
86
+ *
87
+ * @example
88
+ * blockedCategories: ['gambling', 'crypto', 'dating']
89
+ */
90
+ blockedCategories?: string[];
91
+ /**
92
+ * Never show ads from these advertisers.
93
+ * Use advertiser IDs from previous ad responses.
94
+ *
95
+ * @example
96
+ * blockedAdvertisers: ['adv_abc123', 'adv_xyz789']
97
+ */
98
+ blockedAdvertisers?: string[];
66
99
  }
67
100
  interface DecideResponse {
68
101
  request_id: string;
@@ -557,6 +590,44 @@ interface GetServiceRequest {
557
590
  region?: string;
558
591
  };
559
592
  }
593
+ interface IABCategory {
594
+ /** Unique IAB category ID */
595
+ id: number;
596
+ /** Parent category ID (null for tier 1 categories) */
597
+ parent_id: number | null;
598
+ /** Category name */
599
+ name: string;
600
+ /** Tier 1 category (top level) */
601
+ tier_1: string | null;
602
+ /** Tier 2 category (sub-category) */
603
+ tier_2: string | null;
604
+ /** Tier 3 category (sub-sub-category) */
605
+ tier_3: string | null;
606
+ /** Tier 4 category (deepest level) */
607
+ tier_4: string | null;
608
+ /** Full hierarchical path (e.g., "Automotive > Auto Insurance") */
609
+ full_path: string;
610
+ }
611
+ interface CategoryTaxonomyResponse {
612
+ /** Taxonomy version */
613
+ version: string;
614
+ /** Source organization */
615
+ source: string;
616
+ /** Reference URL */
617
+ url: string;
618
+ /** Total number of categories returned (after filtering) */
619
+ total: number;
620
+ /** Array of categories */
621
+ categories: IABCategory[];
622
+ }
623
+ interface GetCategoriesParams {
624
+ /** Filter by tier level (1-4) */
625
+ tier?: 1 | 2 | 3 | 4;
626
+ /** Filter by parent category ID */
627
+ parent_id?: number;
628
+ /** Search by name or path (case-insensitive) */
629
+ search?: string;
630
+ }
560
631
 
561
632
  /**
562
633
  * Utility functions for the AttentionMarket SDK.
@@ -989,6 +1060,39 @@ declare class AttentionMarketClient {
989
1060
  * ```
990
1061
  */
991
1062
  logServiceResult(params: ServiceResultRequest): Promise<ServiceResultResponse>;
1063
+ /**
1064
+ * Get IAB Content Taxonomy categories.
1065
+ *
1066
+ * Returns the complete IAB Content Taxonomy 3.0 (704 categories across 38 top-level categories).
1067
+ * Supports filtering by tier level, parent category, or search term.
1068
+ *
1069
+ * Use this to discover available categories for `allowedCategories` and `blockedCategories` parameters.
1070
+ *
1071
+ * @param params - Optional filters (tier, parent_id, search)
1072
+ * @returns The IAB Content Taxonomy with categories
1073
+ *
1074
+ * @example Get all Tier 1 categories (38 top-level categories)
1075
+ * ```typescript
1076
+ * const tier1 = await client.getCategories({ tier: 1 });
1077
+ * console.log(`${tier1.total} top-level categories`);
1078
+ * tier1.categories.forEach(cat => console.log(`${cat.id}: ${cat.name}`));
1079
+ * ```
1080
+ *
1081
+ * @example Get all subcategories of "Automotive" (ID: 1)
1082
+ * ```typescript
1083
+ * const automotiveCategories = await client.getCategories({ parent_id: 1 });
1084
+ * console.log(`Found ${automotiveCategories.total} automotive subcategories`);
1085
+ * ```
1086
+ *
1087
+ * @example Search for insurance-related categories
1088
+ * ```typescript
1089
+ * const insuranceCategories = await client.getCategories({ search: 'insurance' });
1090
+ * insuranceCategories.categories.forEach(cat => {
1091
+ * console.log(`${cat.id}: ${cat.full_path}`);
1092
+ * });
1093
+ * ```
1094
+ */
1095
+ getCategories(params?: GetCategoriesParams): Promise<CategoryTaxonomyResponse>;
992
1096
  }
993
1097
 
994
1098
  /**
package/dist/index.d.ts CHANGED
@@ -63,6 +63,39 @@ interface DecideFromContextRequest {
63
63
  language?: string;
64
64
  /** User's platform. Default: 'web' */
65
65
  platform?: 'web' | 'ios' | 'android' | 'desktop' | 'voice' | 'other';
66
+ /**
67
+ * Minimum quality score threshold (0.0 - 1.0).
68
+ * Only return ads with quality scores at or above this value.
69
+ * Higher values = better quality but lower fill rate.
70
+ *
71
+ * @example
72
+ * minQualityScore: 0.8 // Only show ads with 0.8+ quality
73
+ */
74
+ minQualityScore?: number;
75
+ /**
76
+ * Only show ads from these categories.
77
+ * If set, blockedCategories is ignored.
78
+ *
79
+ * @example
80
+ * allowedCategories: ['wedding', 'photography', 'venues']
81
+ */
82
+ allowedCategories?: string[];
83
+ /**
84
+ * Never show ads from these categories.
85
+ * Ignored if allowedCategories is set.
86
+ *
87
+ * @example
88
+ * blockedCategories: ['gambling', 'crypto', 'dating']
89
+ */
90
+ blockedCategories?: string[];
91
+ /**
92
+ * Never show ads from these advertisers.
93
+ * Use advertiser IDs from previous ad responses.
94
+ *
95
+ * @example
96
+ * blockedAdvertisers: ['adv_abc123', 'adv_xyz789']
97
+ */
98
+ blockedAdvertisers?: string[];
66
99
  }
67
100
  interface DecideResponse {
68
101
  request_id: string;
@@ -557,6 +590,44 @@ interface GetServiceRequest {
557
590
  region?: string;
558
591
  };
559
592
  }
593
+ interface IABCategory {
594
+ /** Unique IAB category ID */
595
+ id: number;
596
+ /** Parent category ID (null for tier 1 categories) */
597
+ parent_id: number | null;
598
+ /** Category name */
599
+ name: string;
600
+ /** Tier 1 category (top level) */
601
+ tier_1: string | null;
602
+ /** Tier 2 category (sub-category) */
603
+ tier_2: string | null;
604
+ /** Tier 3 category (sub-sub-category) */
605
+ tier_3: string | null;
606
+ /** Tier 4 category (deepest level) */
607
+ tier_4: string | null;
608
+ /** Full hierarchical path (e.g., "Automotive > Auto Insurance") */
609
+ full_path: string;
610
+ }
611
+ interface CategoryTaxonomyResponse {
612
+ /** Taxonomy version */
613
+ version: string;
614
+ /** Source organization */
615
+ source: string;
616
+ /** Reference URL */
617
+ url: string;
618
+ /** Total number of categories returned (after filtering) */
619
+ total: number;
620
+ /** Array of categories */
621
+ categories: IABCategory[];
622
+ }
623
+ interface GetCategoriesParams {
624
+ /** Filter by tier level (1-4) */
625
+ tier?: 1 | 2 | 3 | 4;
626
+ /** Filter by parent category ID */
627
+ parent_id?: number;
628
+ /** Search by name or path (case-insensitive) */
629
+ search?: string;
630
+ }
560
631
 
561
632
  /**
562
633
  * Utility functions for the AttentionMarket SDK.
@@ -989,6 +1060,39 @@ declare class AttentionMarketClient {
989
1060
  * ```
990
1061
  */
991
1062
  logServiceResult(params: ServiceResultRequest): Promise<ServiceResultResponse>;
1063
+ /**
1064
+ * Get IAB Content Taxonomy categories.
1065
+ *
1066
+ * Returns the complete IAB Content Taxonomy 3.0 (704 categories across 38 top-level categories).
1067
+ * Supports filtering by tier level, parent category, or search term.
1068
+ *
1069
+ * Use this to discover available categories for `allowedCategories` and `blockedCategories` parameters.
1070
+ *
1071
+ * @param params - Optional filters (tier, parent_id, search)
1072
+ * @returns The IAB Content Taxonomy with categories
1073
+ *
1074
+ * @example Get all Tier 1 categories (38 top-level categories)
1075
+ * ```typescript
1076
+ * const tier1 = await client.getCategories({ tier: 1 });
1077
+ * console.log(`${tier1.total} top-level categories`);
1078
+ * tier1.categories.forEach(cat => console.log(`${cat.id}: ${cat.name}`));
1079
+ * ```
1080
+ *
1081
+ * @example Get all subcategories of "Automotive" (ID: 1)
1082
+ * ```typescript
1083
+ * const automotiveCategories = await client.getCategories({ parent_id: 1 });
1084
+ * console.log(`Found ${automotiveCategories.total} automotive subcategories`);
1085
+ * ```
1086
+ *
1087
+ * @example Search for insurance-related categories
1088
+ * ```typescript
1089
+ * const insuranceCategories = await client.getCategories({ search: 'insurance' });
1090
+ * insuranceCategories.categories.forEach(cat => {
1091
+ * console.log(`${cat.id}: ${cat.full_path}`);
1092
+ * });
1093
+ * ```
1094
+ */
1095
+ getCategories(params?: GetCategoriesParams): Promise<CategoryTaxonomyResponse>;
992
1096
  }
993
1097
 
994
1098
  /**
package/dist/index.js CHANGED
@@ -529,7 +529,12 @@ var AttentionMarketClient = class {
529
529
  }
530
530
  },
531
531
  context,
532
- user_intent: params.userMessage
532
+ user_intent: params.userMessage,
533
+ // Developer controls (Phase 1: Quality & Brand Safety)
534
+ ...params.minQualityScore !== void 0 && { minQualityScore: params.minQualityScore },
535
+ ...params.allowedCategories && { allowedCategories: params.allowedCategories },
536
+ ...params.blockedCategories && { blockedCategories: params.blockedCategories },
537
+ ...params.blockedAdvertisers && { blockedAdvertisers: params.blockedAdvertisers }
533
538
  };
534
539
  const response = await this.decideRaw(request, options);
535
540
  if (response.status === "no_fill" || response.units.length === 0) {
@@ -1156,6 +1161,55 @@ var AttentionMarketClient = class {
1156
1161
  { body: params }
1157
1162
  );
1158
1163
  }
1164
+ /**
1165
+ * Get IAB Content Taxonomy categories.
1166
+ *
1167
+ * Returns the complete IAB Content Taxonomy 3.0 (704 categories across 38 top-level categories).
1168
+ * Supports filtering by tier level, parent category, or search term.
1169
+ *
1170
+ * Use this to discover available categories for `allowedCategories` and `blockedCategories` parameters.
1171
+ *
1172
+ * @param params - Optional filters (tier, parent_id, search)
1173
+ * @returns The IAB Content Taxonomy with categories
1174
+ *
1175
+ * @example Get all Tier 1 categories (38 top-level categories)
1176
+ * ```typescript
1177
+ * const tier1 = await client.getCategories({ tier: 1 });
1178
+ * console.log(`${tier1.total} top-level categories`);
1179
+ * tier1.categories.forEach(cat => console.log(`${cat.id}: ${cat.name}`));
1180
+ * ```
1181
+ *
1182
+ * @example Get all subcategories of "Automotive" (ID: 1)
1183
+ * ```typescript
1184
+ * const automotiveCategories = await client.getCategories({ parent_id: 1 });
1185
+ * console.log(`Found ${automotiveCategories.total} automotive subcategories`);
1186
+ * ```
1187
+ *
1188
+ * @example Search for insurance-related categories
1189
+ * ```typescript
1190
+ * const insuranceCategories = await client.getCategories({ search: 'insurance' });
1191
+ * insuranceCategories.categories.forEach(cat => {
1192
+ * console.log(`${cat.id}: ${cat.full_path}`);
1193
+ * });
1194
+ * ```
1195
+ */
1196
+ async getCategories(params) {
1197
+ const queryParams = new URLSearchParams();
1198
+ if (params?.tier) {
1199
+ queryParams.append("tier", params.tier.toString());
1200
+ }
1201
+ if (params?.parent_id) {
1202
+ queryParams.append("parent_id", params.parent_id.toString());
1203
+ }
1204
+ if (params?.search) {
1205
+ queryParams.append("search", params.search);
1206
+ }
1207
+ const url = `/v1/categories${queryParams.toString() ? "?" + queryParams.toString() : ""}`;
1208
+ return await this.http.request(
1209
+ "GET",
1210
+ url
1211
+ );
1212
+ }
1159
1213
  };
1160
1214
 
1161
1215
  // src/mock-client.ts