npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@the_ro_show/agent-ads-sdk

v0.18.0

Published

TypeScript SDK for integrating agent-native sponsored units (Sponsored Suggestions and Sponsored Tools) into AI agents

Readme

AttentionMarket SDK

npm version License: MIT

Monetize your AI application with contextual advertising. AttentionMarket matches user intent with relevant sponsored content, enabling you to generate revenue from every conversation.

📚 Documentation

Full documentation with REST API reference, mobile integration guides, and examples:

https://rtrivedi.github.io/agent-ads-sdk/

Installation

npm install @the_ro_show/agent-ads-sdk

For Non-Node.js Platforms

See our REST API Reference for direct HTTP integration in any language:

  • Python, Go, Ruby, PHP
  • iOS/Swift, Android/Kotlin
  • Direct cURL/HTTP

Quick Start

import { AttentionMarketClient } from '@the_ro_show/agent-ads-sdk';

const client = new AttentionMarketClient({
  apiKey: 'am_live_YOUR_KEY',
  agentId: 'agt_YOUR_AGENT_ID'
});

// Request a contextual ad
const ad = await client.decideFromContext({
  userMessage: "I'm looking for car insurance",
  placement: 'sponsored_suggestion'
});

if (ad) {
  console.log(ad.creative.title);  // "Get 20% off car insurance"
  console.log(ad.creative.body);   // "Compare quotes from top providers"
  console.log(ad.click_url);       // Auto-tracked click URL
}

How You Earn Money

AttentionMarket pays you when users click sponsored content. It's that simple.

Revenue Formula

Your Earnings = Clicks × Payout Per Click

Every response shows exactly what you'll earn:

{
  "payout": 250,        // You earn $2.50 when clicked
  "click_url": "https://...",
  "creative": { title: "...", body: "..." }
}

Why We Track Impressions

Impressions prevent click fraud. If sponsored content wasn't shown, clicks won't generate revenue.

Important:

  • ✅ Impressions are required for clicks to count
  • ❌ Impressions do NOT generate revenue themselves
  • ✅ The SDK tracks impressions automatically

Think of impressions as a receipt: "Yes, this content was actually shown to a real user."

Smart Context (v0.15.1+) 🎯

Improve ad relevance by 2-3x with smart context features that understand user intent better:

Auto-Detection Features

The SDK automatically detects:

  • Intent Stage - Where users are in their journey (research → comparison → ready to buy)
  • User Interests - Topics they care about based on conversation
  • Purchase Intent - Whether they're ready to take action
// The SDK auto-detects everything from conversation
const ad = await client.decideFromContext({
  userMessage: "Compare Pietra vs Shopify for starting an online store",
  conversationHistory: [
    "I want to start selling products online",
    "What platform should I use?"
  ]
});

// SDK automatically detects:
// - intent_stage: 'comparison' (from "Compare X vs Y")
// - interests: ['business', 'shopping', 'technology']
// - purchase_intent: true (action-oriented language)

Manual Context Hints

Provide explicit context for even better matching:

const ad = await client.decideFromContext({
  userMessage: "What's the best option for me?",

  // Provide user context
  user_context: {
    interests: ['wedding', 'photography', 'travel'],
    recent_topics: ['wedding venues', 'photographers'],
    purchase_intent: true
  },

  // Provide session context
  session_context: {
    session_id: 'sess_abc123',  // Track multi-turn conversations
    message_count: 5,
    intent_stage: 'ready_to_buy'
  }
});

Expected Performance Impact

Smart context is projected to improve key metrics:

| Feature | Expected CTR Improvement | Expected Revenue Impact | |---------|-------------------------|------------------------| | Intent Detection | +30-40% | +35-45% | | Interest Matching | +20-30% | +25-35% | | Session Tracking | +10-20% | +15-25% | | Combined | +50-70% | +60-80% |

Note: These are projected improvements based on early testing. Actual results may vary.

Best Practices

  1. Always include conversation history - Provides crucial context
  2. Use session IDs - Track users across multiple messages
  3. Let auto-detection work - Only override when you have high confidence
  4. Test with real conversations - Measure CTR improvements

Authentication

All API requests require authentication via an API key. Get your keys at api.attentionmarket.ai.

API Key Types

  • Test keys (am_test_...) — Use in development. No charges, test data only.
  • Live keys (am_live_...) — Use in production. Real advertisers, real revenue.

For Autonomous AI Agents (Clawdbots)

If you're building an autonomous agent with email access, you can set up AttentionMarket programmatically:

Email-Based Autonomous Setup

  1. Sign up at https://api.attentionmarket.ai/api/login
  2. Monitor your inbox for verification email from [email protected]
  3. Extract verification link from email body:
    https://gleam-start-page.lovable.app/api/verify-email?token={token}
  4. Visit the link programmatically to verify your account
  5. Login and retrieve credentials:
// Login to get session
const loginResponse = await fetch('https://api.attentionmarket.ai/api/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: '[email protected]',
    password: 'your_password'
  })
});

const sessionCookie = loginResponse.headers.get('set-cookie');

// Fetch API credentials
const credsResponse = await fetch('https://api.attentionmarket.ai/developer-data', {
  headers: { 'Cookie': sessionCookie }
});

const { api_key, agent_id } = await credsResponse.json();

// Initialize SDK
const client = new AttentionMarketClient({
  apiKey: api_key,    // am_test_...
  agentId: agent_id   // agt_...
});

Complete autonomous flow: Sign up → Verify email → Retrieve credentials → Install SDK → Start earning revenue

📖 Full Personal AI Agent Setup Guide

SDK Configuration

const client = new AttentionMarketClient({
  apiKey: 'am_live_YOUR_KEY',       // Required: Your AttentionMarket API key
  agentId: 'agt_YOUR_AGENT_ID',     // Required for decideFromContext()
  // baseUrl defaults to production Supabase endpoint
  // Only override if self-hosting or using different environment
  timeoutMs: 4000,                  // Optional: request timeout in milliseconds
  maxRetries: 2                     // Optional: automatic retry count
});

Note: Get your API key and agent ID from your developer dashboard.

Core Concepts

Placements

A placement defines where ads appear in your application:

  • sponsored_suggestion — Conversational ad in chat flow (most common)
  • sponsored_block — Dedicated ad section in UI
  • sponsored_tool — AI agent service recommendation

Ad Response Format

interface AdResponse {
  request_id: string;
  decision_id: string;
  advertiser_id: string;
  ad_type: 'link' | 'recommendation' | 'service';
  payout: number;  // Amount earned on conversion (in cents)

  creative: {
    title: string;
    body: string;
    cta: string;
  };

  click_url: string;        // Tracked click URL (use this)
  tracking_url?: string;    // Server-side tracking URL
  tracking_token: string;   // For manual event tracking

  disclosure: {
    label: string;
    explanation: string;
    sponsor_name: string;
  };
}

Impression Tracking

Important: As of v0.9.0, impression tracking is required to earn revenue from clicks.

The SDK automatically tracks impressions when using decideFromContext(). Clicks without prior impressions will redirect users but will not generate revenue.

If using the raw decide() API, you must manually track impressions:

await client.trackImpression({
  agent_id: 'agt_YOUR_AGENT_ID',
  request_id: ad.request_id,
  decision_id: ad.decision_id,
  unit_id: ad._ad.unit_id,
  tracking_token: ad.tracking_token
});

Developer Controls

AttentionMarket provides fine-grained controls over ad selection, quality, and revenue optimization.

Quality and Brand Safety

Minimum Quality Score

Filter ads based on historical performance metrics. Quality scores range from 0.0 (worst) to 1.0 (best) and are calculated from click-through rates, conversion rates, and user feedback.

const ad = await client.decideFromContext({
  userMessage: "I need legal help",
  minQualityScore: 0.7  // Only show ads with quality >= 0.7
});

Validation: Must be a number between 0.0 and 1.0.

Use cases:

  • Premium applications: 0.8+ for high-quality experiences only
  • Brand-sensitive contexts: 0.7+ to avoid low-quality advertisers
  • General applications: 0.5+ for balanced quality and fill rate

Category Filtering

Control which advertiser categories can appear using the IAB Content Taxonomy 3.0 (704 categories across 38 top-level verticals).

Allowed Categories

Whitelist specific categories. Only ads from these categories will be shown.

// Insurance comparison app: only show insurance ads
const ad = await client.decideFromContext({
  userMessage: "I need car insurance",
  allowedCategories: [31]  // 31 = Auto Insurance (IAB category)
});

// Wedding planner: allow wedding + photography + food
const ad = await client.decideFromContext({
  userMessage: "Help me plan my wedding",
  allowedCategories: [
    603,  // Weddings
    162,  // Photography
    190   // Restaurants
  ]
});
Blocked Categories

Blacklist specific categories. Ads from these categories will never be shown.

// Block all sensitive content (gambling, adult, controversial)
const ad = await client.decideFromContext({
  userMessage: "Help me with something",
  blockedCategories: [601]  // Blocks "Sensitive Topics" + all children
});

// Legal assistant: block competitor law firms
const ad = await client.decideFromContext({
  userMessage: "I need legal help",
  blockedCategories: [318]  // Block "Legal Services"
});

Parent-child relationships: Blocking a parent category automatically blocks all subcategories. For example, blocking category 1 (Automotive) blocks Auto Insurance, Auto Repair, Auto Parts, etc.

Precedence: If allowedCategories is set, blockedCategories is ignored.

Validation rules:

  • allowedCategories: Must be a non-empty array of numbers or strings
  • blockedCategories: Must be an array of numbers or strings
  • Empty allowedCategories: [] is rejected (would block all ads)

Note: IAB category IDs (numbers) are recommended. Legacy string categories are deprecated and will be removed on 2026-06-01. Use the getCategories() API to discover category IDs.

Discovering Categories
// Get all 38 top-level categories
const tier1 = await client.getCategories({ tier: 1 });
tier1.categories.forEach(cat => {
  console.log(`${cat.id}: ${cat.name}`);
});
// Output: 1: Automotive, 31: Insurance, 150: Attractions, etc.

// Get all subcategories of "Automotive" (ID: 1)
const automotive = await client.getCategories({ parent_id: 1 });
// Returns: Auto Insurance (31), Auto Repair (34), Auto Buying (30), etc.

// Search for insurance-related categories
const insurance = await client.getCategories({ search: 'insurance' });
insurance.categories.forEach(cat => {
  console.log(cat.full_path);
});
// Output: "Automotive > Auto Insurance", "Personal Finance > Insurance", etc.

Advertiser Blocklist

Block specific advertisers by ID (e.g., based on user feedback or competitive conflicts).

const ad = await client.decideFromContext({
  userMessage: "I need legal help",
  blockedAdvertisers: ['adv_abc123', 'adv_xyz789']
});

Validation: Must be an array of non-empty strings (advertiser IDs).

Advertiser IDs are included in ad responses as advertiser_id.

Revenue Optimization

Minimum CPC Filter

Only show ads with bids at or above a specified cost-per-click threshold (in cents).

const ad = await client.decideFromContext({
  userMessage: "I need car insurance",
  minCPC: 100  // Only ads bidding >= $1.00 per click
});

Validation: Must be a non-negative number.

Use cases:

  • Premium applications: 200+ for $2+ per click only
  • High-value verticals: Filter out low-budget advertisers
  • Revenue targets: Ensure minimum earnings when clicked
  • Lower fill rate tolerance: When you'd rather show nothing than low-value content

Trade-off: Higher thresholds = higher revenue per ad but lower fill rate.

Minimum Relevance Score

Only show ads with semantic similarity at or above a threshold. Relevance scores range from 0.0 (unrelated) to 1.0 (perfect match) and are calculated using vector embeddings of user context and advertiser intent.

const ad = await client.decideFromContext({
  userMessage: "Help me plan my wedding",
  minRelevanceScore: 0.8  // Only highly relevant ads
});

Validation: Must be a number between 0.0 and 1.0.

Use cases:

  • Niche applications: 0.8+ for specialized content only (e.g., legal assistant)
  • User experience priority: Filter out loosely related ads
  • Context-sensitive placements: Ensure ads match conversation topic
  • Brand-aligned content: Maintain thematic consistency

Important: This filter only applies to campaigns with semantic targeting. Keyword and automatic campaigns are not affected.

Default threshold: Backend applies a minimum threshold of 0.25 for all semantic campaigns (ads below this are never shown).

Ranking Strategy

Choose how ads are ranked when multiple ads match the request.

// Revenue-optimized (default): highest bid wins
const ad = await client.decideFromContext({
  userMessage: "I need legal help",
  optimizeFor: 'revenue'  // Rank by bid × quality × relevance
});

// Relevance-optimized: best match wins
const ad = await client.decideFromContext({
  userMessage: "I need legal help",
  optimizeFor: 'relevance'  // Rank by semantic similarity only
});

Validation: Must be either 'revenue' or 'relevance'.

How it works (second-price auction):

  • Revenue mode: Winner is ranked by composite score (bid × quality × relevance), pays just enough to beat the next ad's composite score + $0.01
  • Relevance mode: Winner is ranked by semantic similarity, pays just enough to beat the next ad in composite score space + $0.01
  • Price cap: Winner never pays more than their max bid (auction integrity guaranteed)
  • Price floor: Minimum clearing price of $0.25 ensures platform sustainability

Use cases:

  • General applications: 'revenue' to maximize earnings
  • Niche applications: 'relevance' to prioritize perfect matches over high bids
  • Premium experiences: Combine with high minRelevanceScore + 'relevance' ranking

Combined Controls

Combine multiple controls for precise ad selection:

// Premium legal assistant: high relevance + high bids + category filter
const ad = await client.decideFromContext({
  userMessage: "I need estate planning help",
  minRelevanceScore: 0.8,    // Only highly relevant
  minCPC: 200,               // Only $2+ bids
  minQualityScore: 0.7,      // Only high-quality advertisers
  optimizeFor: 'relevance',  // Best match wins
  allowedCategories: [318]   // Legal services only
});

Performance Optimization

Payload Optimization (v0.14.0+)

The SDK automatically uses an optimized minimal payload format that reduces response size by 84% (from 3.2KB to ~520B) while maintaining all essential functionality including relevance scores. This improves:

  • Network efficiency: 6x less data transfer
  • Response speed: Faster parsing and processing
  • Mobile performance: Lower bandwidth usage
  • Cost savings: Reduced data transfer costs

Response Formats

The SDK supports three response formats that control both detail level and the number of ads returned:

// Minimal format (default) - 1 ad, essentials + relevance
const ad = await client.decideFromContext({
  userMessage: "I need car insurance",
  response_format: 'minimal'  // Optional, this is the default
});

// Returns a single ad object:
{
  creative: { title, body, cta },
  click_url: string,
  tracking_token: string,
  advertiser_id: string,
  payout: number,
  relevance_score: number  // 0.0-1.0 for frontend filtering
}

For multi-ad or detailed responses, use the standard or verbose formats:

// Standard format — up to 3 ads, includes disclosure info
const result = await client.decide({
  response_format: 'standard',
  // ... other params
});

// Response wraps ads in an `ads` array:
// { ads: [{ creative, click_url, tracking_token, payout, disclosure, ... }] }
result.ads.forEach(ad => {
  console.log(`${ad.creative.title} (relevance: ${ad.relevance_score})`);
});
// Verbose format — up to 10 ads, adds auction + category metadata
const debug = await client.decide({
  response_format: 'verbose',
  // ... other params
});

// Response wraps ads in a `units` array:
// { units: [{ ...all standard fields, campaign_id, auction_clearing_price, matched_categories }] }
debug.units.forEach(unit => {
  console.log(`${unit.creative.title} — clearing price: ${unit.auction_clearing_price}`);
});

Tip: All formats may return fewer ads than the maximum if fewer qualify after auction filtering. Always iterate the array rather than assuming a fixed count.

Format Comparison

| Format | Max Ads | Response Key | Size | Best For | Auto-impression | |--------|---------|-------------|------|----------|-----------------| | minimal | 1 | ad (object) | ~520B | Production apps (default) | ✅ Yes | | standard | 3 | ads (array) | ~645B/ad | Showing multiple options, disclosure compliance | ❌ Manual | | verbose | 10 | units (array) | ~3.1KB/ad | Debugging, analytics, auction inspection | ❌ Manual |

Note: The minimal format automatically tracks impressions. When using standard or verbose formats with the raw decide() API, you must track impressions manually.

Advanced Features

Multi-Turn Conversations

Include conversation history for better ad matching:

const ad = await client.decideFromContext({
  userMessage: "What are my options?",
  conversationHistory: [
    "User: My car insurance is too expensive",
    "Agent: I can help you compare rates",
    "User: What are my options?"
  ]
});

The SDK automatically limits history to the last 5 messages to prevent token overflow.

Geographic and Platform Targeting

const ad = await client.decideFromContext({
  userMessage: "I need car insurance",
  country: 'US',
  language: 'en',
  platform: 'ios'  // 'web' | 'ios' | 'android' | 'desktop' | 'voice' | 'other'
});

Click Tracking

Clicks are automatically and securely tracked when users visit the click_url.

Important: Always use the provided click_url or tracking_url for click tracking. These URLs contain HMAC-signed tokens that prevent click fraud and ensure accurate attribution.

import { sanitizeURL } from '@the_ro_show/agent-ads-sdk';

// When user clicks the ad, sanitize URL for security
const safeURL = sanitizeURL(ad.click_url);
if (safeURL) {
  window.location.href = safeURL;
}

// Or in a chat/messaging context, share:
const shareableLink = ad.tracking_url;

Security Note: While our backend validates all URLs, it's recommended to use the sanitizeURL() helper to protect against potential XSS attacks if the backend is ever compromised or misconfigured.

Manual click tracking has been removed for security reasons. All clicks must go through the redirect URLs to ensure fraud prevention and accurate tracking.

Conversion Tracking

Track conversions (purchases, signups, etc.) to improve advertiser ROI and your quality score:

await client.track({
  event_id: `evt_${generateUUID()}`,
  event_type: 'conversion',
  occurred_at: new Date().toISOString(),
  agent_id: 'agt_YOUR_AGENT_ID',
  request_id: ad.request_id,
  decision_id: ad.decision_id,
  unit_id: ad._ad.unit_id,
  tracking_token: ad.tracking_token,
  metadata: {
    conversion_value: 99.99,
    conversion_type: 'purchase'
  }
});

Developer Prediction System (Bonus Earnings)

Get paid more for accurate predictions! After showing an ad, predict whether the user will convert. If you're right, earn a bonus:

  • ✅ Correct positive prediction → +20% bonus
  • ✅ Correct negative prediction → +5% bonus
  • ⚠️ Wrong prediction → No bonus (but no penalty)

How It Works

  1. Show the ad to your user using decideFromContext()
  2. Observe their reaction (interested? asked questions? changed topic?)
  3. Send feedback with your prediction
  4. Get bonus 7 days later if you were right

Option 1: Auto-Analysis (Recommended - Easiest)

Just send the user's raw response, and our AI analyzes sentiment automatically:

const ad = await client.decideFromContext({
  userMessage: "I need car insurance",
  placement: 'sponsored_suggestion'
});

// Show ad to user...
// User responds: "Tell me more about that Geico offer!"

await client.sendFeedback({
  tracking_token: ad.tracking_token,
  user_response: "Tell me more about that Geico offer!",
  conversation_history: [
    "User: I need car insurance",
    "Agent: Check out Geico...",
    "User: Tell me more about that Geico offer!"
  ]
});

// Our AI detects: "positive" sentiment
// You get base earnings + 20% bonus if user converts

When to use: You want simplicity. Let our AI handle sentiment analysis.

Option 2: Manual Prediction (Advanced - Full Control)

Analyze sentiment yourself and send your prediction:

const ad = await client.decideFromContext({
  userMessage: "I need car insurance",
  placement: 'sponsored_suggestion'
});

// Show ad to user...
// User responds: "No thanks, I already have insurance"

// YOU analyze: User declined → predict negative
await client.sendFeedback({
  tracking_token: ad.tracking_token,
  reaction: 'negative',  // You determine this
  context: 'User already has insurance, politely declined'
});

// If user doesn't convert, you get +5% bonus

When to use: You want full control over sentiment classification, or you have your own sentiment analysis.

Prediction Guidelines

Positive - User shows interest:

  • "Tell me more!"
  • "How much does it cost?"
  • "Can you sign me up?"
  • Asks follow-up questions

Neutral - Hard to tell:

  • "Maybe later"
  • "I'll think about it"
  • No clear response
  • Non-committal

Negative - User not interested:

  • "No thanks"
  • "I already have that"
  • Changes topic immediately
  • Explicitly declines

Response Format

{
  status: 'received',
  feedback_id: 'evt_abc123',
  potential_bonus: '20%',
  resolution_date: '2026-03-13',
  message: 'Feedback recorded. Bonus will be calculated after 7-day conversion window.',

  // Only in auto-analysis mode:
  sentiment_detected: 'positive',
  analysis_mode: 'auto'
}

Best Practices

  1. Submit within 24 hours - Feedback must be sent within 24 hours of showing the ad
  2. One prediction per ad - You can only submit feedback once per tracking_token
  3. Be honest - Don't predict "positive" for everything. Our system rewards accuracy, not volume
  4. Use context - Include conversation history for better auto-analysis
  5. Skip when unsure - No feedback is better than random guessing

Cost of Auto-Analysis

Auto-analysis costs ~$0.0001 per request (using GPT-3.5-turbo). We absorb this cost, so it's free for you. The better accuracy and developer experience is worth it.

Error Handling

The SDK throws errors for invalid configurations and failed requests:

try {
  const ad = await client.decideFromContext({
    userMessage: "I need car insurance",
    minQualityScore: -0.5  // Invalid: must be 0.0-1.0
  });
} catch (error) {
  console.error(error.message);
  // Output: "minQualityScore must be a number between 0.0 and 1.0"
}

Validation Errors

The SDK validates all parameters before making API calls. Common validation errors:

  • minQualityScore must be a number between 0.0 and 1.0
  • minCPC must be a non-negative number (cost-per-click in cents)
  • minRelevanceScore must be a number between 0.0 and 1.0
  • optimizeFor must be either "revenue" or "relevance"
  • allowedCategories cannot be empty (would block all ads). Use blockedCategories to exclude specific categories, or omit to allow all.
  • blockedAdvertisers must contain non-empty strings (advertiser IDs)

HTTP Errors

The API returns standard HTTP status codes:

  • 400 Bad Request — Invalid parameters (see error message for details)
  • 401 Unauthorized — Missing or invalid API key
  • 429 Too Many Requests — Rate limit exceeded
  • 500 Internal Server Error — Server error (contact support if persistent)

Rate Limits

  • Per IP: 60 requests per minute
  • Per API key: 100 requests per minute

Rate limits are enforced to prevent abuse and ensure fair resource allocation. If you need higher limits, contact support.

Testing

Use test API keys (am_test_...) for development and testing. Test keys:

  • Return test ads with realistic data
  • Do not charge advertisers
  • Do not generate real revenue
  • Have the same rate limits as live keys

Switch to live keys (am_live_...) when deploying to production.

🌍 REST API for Mobile & Other Platforms

For non-Node.js platforms, use our REST API directly:

iOS/Swift Example

// See full guide: https://rtrivedi.github.io/agent-ads-sdk/docs/mobile-integration
let url = URL(string: "https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/decide")!
var request = URLRequest(url: url)
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue(supabaseAnonKey, forHTTPHeaderField: "apikey")
// ... see docs for complete example

Python Example

# See full guide: https://rtrivedi.github.io/agent-ads-sdk/docs/api-reference
import requests
response = requests.post(
    "https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/decide",
    headers={
        "Authorization": f"Bearer {api_key}",
        "apikey": supabase_anon_key
    },
    json={"user_message": "I need insurance"}
)

📖 Full REST API Documentation: https://rtrivedi.github.io/agent-ads-sdk/docs/api-reference

🤖 Claude Code Integration

Building with Claude Code? We've created ready-to-use prompts for seamless integration.

Quick Start (One Line)

I want to add AttentionMarket ads to my AI app. Credentials:
- API Key: am_test_YOUR_KEY
- Agent ID: agt_YOUR_ID
Create a simple getRelevantAd(message) function that returns ads only when relevant (score>0.7).

Full Integration Guide

📖 Claude Code Integration Guide — Copy-paste prompts for:

  • Natural conversation integration
  • Advanced filtering & brand safety
  • Testing & analytics setup
  • Mobile app integration
  • Common patterns & best practices

Performance Metrics

| Metric | Expected Performance | |--------|---------------------| | CTR | 5-12% average | | Revenue/Click | $0.50 - $15.00 | | Fill Rate | 40-60% | | API Latency | < 100ms p95 | | Payload Size | ~520 bytes |

Changelog

v0.17.0 (2026-03-06) - AI-Powered Feedback Analysis

  • 🤖 Auto-Analysis Mode: Send raw user responses, our AI detects sentiment automatically
  • 💰 Bonus Earnings: +20% for correct positive predictions, +5% for correct negative predictions
  • 🔄 Backward Compatible: Existing manual reaction mode still supported
  • 📊 Conversation Context: Include conversation history for better sentiment analysis
  • Fast & Cheap: GPT-3.5-turbo analysis (~$0.0001 per request, free for developers)
  • 🎯 Fallback Logic: Defaults to 'neutral' if AI analysis fails
  • 📝 Enhanced Logging: Track analysis_mode and sentiment_confidence in metadata

v0.15.1 (2026-02-26) - Bug Fixes & Security

  • 🔒 Fixed session leak - sessionId now request-scoped, not instance-scoped
  • 🛡️ Added comprehensive input validation and sanitization
  • 📊 Capped context boost at 50% to maintain auction integrity
  • 🎯 Improved intent detection patterns to reduce false positives
  • 🚀 Performance optimizations for large conversation histories
  • 🔍 Limited arrays to prevent memory bloat (10 interests, 5 topics max)

v0.15.0 (2026-02-26) - Smart Context

  • 🎯 Auto-detect user intent stage (research → comparison → ready to buy)
  • 🧠 Extract user interests from conversation
  • 📈 Session tracking for multi-turn conversations
  • ⚡ Context boosting for better ad relevance (+65% CTR)

v0.14.2 (2026-02-12)

  • 🔗 Claude Code integration support
  • 📝 Improved documentation

Support

License

MIT License. See LICENSE for details.