Skip to main content

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 40 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;
  }
}

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