Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.thrads.ai/llms.txt

Use this file to discover all available pages before exploring further.

Handle Timeouts Gracefully

The endpoint has built-in timeouts (~3s max). Always set a client-side timeout as well:
try {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), 5000);
  
  const response = await fetch(url, {
    signal: controller.signal,
    // ... rest of config
  });
  
  clearTimeout(timeout);
  return await response.json();
} catch (error) {
  console.error('Bid request failed:', error);
  return null;
}

Respect Rate Limits

The API supports 100 requests per second per API key. Monitor rate limit headers:
const rateLimitRemaining = response.headers.get('X-RateLimit-Remaining');
const rateLimitReset = response.headers.get('X-RateLimit-Reset');

if (rateLimitRemaining < 10) {
  console.warn('Approaching rate limit');
}

CORS Configuration

For browser-based requests, register your domains with Thrad:
  • Contact contact@thrad.ai to whitelist your domains
  • Include the Origin header in requests
  • Handle CORS preflight requests properly

Maintain Conversation Context

Keep the conversation history accurate for better ad relevance:
let conversationHistory = [];

function addMessage(role, content) {
  conversationHistory.push({
    role: role,
    content: content,
    timestamp: new Date().toISOString()
  });
}

function resetConversation() {
  conversationHistory = [];
  sessionStorage.removeItem('thrad_chat_id');
}

Error Handling

Handle all possible response scenarios:
async function handleBidRequest(messages) {
  try {
    const response = await fetchAd(messages, messages.length / 2);
    
    if (!response) {
      return null;
    }
    
    if (response.url && response.description) {
      return response;
    }
    
    return null;
  } catch (error) {
    console.error('Bid request error:', error);
    return null;
  }
}

How Matching Works

A few signals are derived server-side from what you already send — you don’t need to compute them:
  • Conversation language — auto-detected from messages (last few turns). Used by language-targeted campaigns. On opener requests with no messages, the server falls back to the Accept-Language header; if neither is available, language targeting is skipped for that request.
  • Intent & keywords — derived from the conversation content.
  • Geo — from X-User-Country/X-User-Region/X-User-City headers when provided, otherwise from the X-Forwarded-For IP.
This means non-English chats reach language-matched campaigns automatically. If your fill rate dips on a specific language, it’s a supply-side signal (fewer campaigns targeting that language), not a configuration issue on your side. oRTB DSPs scrub or skip requests for EU/UK users that don’t carry a valid IAB TCF v2 consent string. If your platform serves EU/UK traffic and you want full oRTB fill, pass user_metadata.tcf_consent (the raw base64 string from your CMP). The internal Thrad DSP doesn’t gate on TCF — you still get those bids — but external oRTB demand will drop without it. Same applies to California traffic and user_metadata.us_privacy. Non-EU/non-US publishers can ignore both.

Maximising Fill Rate

Fill rate is the percentage of bid requests that return an ad. Several factors affect it: conversation relevance, geo targeting, campaign budgets, and pacing settings. Here’s a recommended approach: Start without force — leave it off (the default) so you only show ads when there’s a strong contextual match. This gives the best user experience and highest click-through rates. Monitor your fill rate — if you’re seeing a fill rate below your target, consider these steps in order:
  1. Lower ad_offset — reduce the number of turns before the first ad. ad_offset: 0 allows ads from the first exchange.
  2. Lower max_frequency — allow ads more frequently within a conversation.
  3. Remove max_headline_chars — headline constraints filter out some ads. Removing the limit increases the pool of eligible creatives.
  4. Enable force: true — as a last resort, force guarantees an ad is served whenever products exist in the system for the user’s geo, even if the conversation context isn’t a strong match.
// Step 1: Start with normal targeting (recommended)
{ "config": { "ad_offset": 3, "max_frequency": 5 } }

// Step 2: If fill rate too low, relax pacing
{ "config": { "ad_offset": 0, "max_frequency": 2 } }

// Step 3: If still too low, enable force
{ "config": { "ad_offset": 0, "max_frequency": 2 }, "force": true }
force: true increases fill rate but may lower relevance and click-through rates. We recommend using config.experiment_tag to A/B test force vs non-force and measure the impact on your metrics before rolling it out fully.

Testing Your Integration

  1. Start with your staging API key: Use the staging-environment key during development — it always returns ads and doesn’t count toward monetization
  2. Test with various conversation flows: Try different topics and conversation lengths
  3. Handle no-bid scenarios: Ensure your UI gracefully handles null bids
  4. Test error scenarios: Verify error handling works correctly
  5. Monitor performance: Track request latency and success rates
  6. Switch to production key only when going live: Production keys enable real targeting, geolocation, and monetization

Support

For questions or assistance, reach out to contact@thrad.ai