Troubleshooting and Debugging Criteo | Blue Frog Docs

Troubleshooting and Debugging Criteo

Comprehensive guide to diagnosing and resolving common Criteo OneTag issues, product feed problems, tracking errors, and integration challenges.

This guide provides solutions to common Criteo implementation issues, debugging techniques, and best practices for maintaining a healthy Criteo integration.

OneTag Troubleshooting

Verify OneTag Installation

Check if the OneTag is properly loaded on your pages:

// Open browser console and run:
console.log(window.criteo_q);

// Should return an array of event objects
// Example output:
// [
//   {event: "setAccount", account: 12345},
//   {event: "setSiteType", type: "d"},
//   {event: "viewItem", item: "PROD123"}
// ]

Common OneTag Issues

1. OneTag Not Loading

Symptoms:

  • window.criteo_q is undefined
  • No Criteo requests in Network tab

Diagnosis:

// Check if script is blocked
if (typeof window.criteo_q === 'undefined') {
  console.error('Criteo OneTag not loaded');
}

// Check Network tab for:
// - dynamic.criteo.com/js/ld/ld.js
// - gum.criteo.com/syncframe

Solutions:

  1. Verify script tag is present in HTML
  2. Check for ad blocker interference
  3. Ensure script is not blocked by Content Security Policy
<!-- Add to CSP header if needed -->
<meta http-equiv="Content-Security-Policy"
      content="script-src 'self' dynamic.criteo.com gum.criteo.com">
  1. Check for JavaScript errors preventing execution

2. Incorrect Account ID

Symptoms:

  • Events fire but no data appears in Criteo dashboard
  • Console errors about invalid account

Diagnosis:

// Verify account ID in console
window.criteo_q.forEach(event => {
  if (event.event === 'setAccount') {
    console.log('Account ID:', event.account);
  }
});

Solutions:

  1. Verify account ID in Criteo Management Center under Settings > Account Information
  2. Ensure account ID is a number, not a string:
// ✗ Wrong
{ event: "setAccount", account: "12345" }

// ✓ Correct
{ event: "setAccount", account: 12345 }

3. Events Not Firing

Symptoms:

  • OneTag loads but specific events don't trigger
  • Product views not recorded

Diagnosis:

// Add debug listener
window.criteo_q.push = function(...args) {
  console.log('Criteo event pushed:', args);
  return Array.prototype.push.apply(this, args);
};

Solutions:

  1. Check event syntax matches Criteo specifications
  2. Verify events fire on correct page types
  3. Ensure data layer is populated before OneTag executes
// ✓ Correct order
<script>
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    productId: 'PROD123',
    productPrice: 99.99
  });
</script>
<script src="//dynamic.criteo.com/js/ld/ld.js" async="true"></script>
<script>
  window.criteo_q = window.criteo_q || [];
  window.criteo_q.push({
    event: "viewItem",
    item: window.dataLayer[0].productId
  });
</script>

4. Device Type Detection Issues

Symptoms:

  • Incorrect device type classification
  • Mobile traffic showing as desktop

Diagnosis:

// Test device type detection
var deviceType = /iPad/.test(navigator.userAgent) ? "t" :
                 /Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Silk/.test(navigator.userAgent) ? "m" : "d";
console.log('Detected device type:', deviceType);
// t = tablet, m = mobile, d = desktop

Solutions:

  1. Use improved device detection:
function getCriteoDeviceType() {
  const ua = navigator.userAgent;

  // Tablet detection
  if (/(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(ua.toLowerCase())) {
    return 't';
  }

  // Mobile detection
  if (/(mobi|ipod|phone|blackberry|opera mini|fennec|minimo|symbian|psp|nintendo ds|archos|skyfire|puffin|blazer|bolt|gobrowser|iris|maemo|semc|teashark|uzard)/.test(ua.toLowerCase())) {
    return 'm';
  }

  // Desktop
  return 'd';
}

window.criteo_q.push({
  event: "setSiteType",
  type: getCriteoDeviceType()
});

Product Feed Issues

Feed Validation Errors

1. Missing Required Fields

Error Message:

"Feed rejected: Missing required field 'image_link' for product PROD123"

Solutions:

  1. Verify all required fields are present:

    • id
    • title
    • description
    • link
    • image_link
    • price
    • availability
  2. Check XML structure:

<!-- ✗ Wrong - missing image_link -->
<product>
  <id>PROD123</id>
  <title>Product Name</title>
  <link>https://example.com/product</link>
  <price>99.99 USD</price>
</product>

<!-- ✓ Correct -->
<product>
  <id>PROD123</id>
  <title>Product Name</title>
  <description>Product description</description>
  <link>https://example.com/product</link>
  <image_link>https://example.com/images/product.jpg</image_link>
  <price>99.99 USD</price>
  <availability>in stock</availability>
</product>

2. Invalid URL Format

Error Message:

"Invalid URL format in field 'link' for product PROD456"

Solutions:

  1. Ensure all URLs are absolute and use HTTPS:
<!-- ✗ Wrong -->
<link>/products/item</link>
<image_link>http://example.com/image.jpg</image_link>

<!-- ✓ Correct -->
<link>https://example.com/products/item</link>
<image_link>https://example.com/images/product.jpg</image_link>
  1. URL encode special characters:
from urllib.parse import quote

# Encode product URLs
product_url = "https://example.com/product?id=123&variant=blue"
encoded_url = quote(product_url, safe=':/?#[]@!$&\'()*+,;=')

3. Price Format Errors

Error Message:

"Invalid price format for product PROD789"

Solutions:

  1. Use correct price format:
<!-- ✗ Wrong -->
<price>$99.99</price>
<price>99,99 EUR</price>
<price>99.99</price>

<!-- ✓ Correct -->
<price>99.99 USD</price>
<price>99.99 EUR</price>
<price>99.99 GBP</price>
  1. Validate currency codes (use ISO 4217):
const validCurrencies = ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY'];

function formatPrice(amount, currency) {
  if (!validCurrencies.includes(currency)) {
    throw new Error(`Invalid currency: ${currency}`);
  }
  return `${parseFloat(amount).toFixed(2)} ${currency}`;
}

4. Character Encoding Issues

Error Message:

"Invalid character encoding in feed"

Solutions:

  1. Ensure UTF-8 encoding:
<?xml version="1.0" encoding="UTF-8"?>
  1. Properly escape special characters:
<title>Product &amp; Accessories</title>
<description>Product with "quotes" and &lt;tags&gt;</description>
  1. Use CDATA for HTML content:
<description><![CDATA[
  <p>Rich product description with <strong>HTML</strong> formatting</p>
]]></description>

Feed Access Issues

1. Feed Not Accessible

Error Message:

"Unable to access feed URL: Connection timeout"

Diagnosis:

# Test feed accessibility
curl -I https://example.com/feeds/products.xml

# Should return 200 OK
# Check response time (should be < 30 seconds)

Solutions:

  1. Verify URL is publicly accessible (not behind authentication)
  2. Check server response time
  3. Enable HTTPS for feed URL
  4. Whitelist Criteo's IP addresses if firewall is blocking

Criteo Crawler IPs to Whitelist:

185.31.17.0/24
185.31.18.0/24
185.31.19.0/24

2. Feed Parsing Errors

Error Message:

"XML parsing error at line 145: Unexpected end of file"

Diagnosis:

  1. Validate XML structure:
# Use xmllint to validate
xmllint --noout products.xml

# Or online validators
curl -X POST https://validator.w3.org/feed/check.cgi \
  -d "url=https://example.com/feeds/products.xml"

Solutions:

  1. Fix malformed XML:
<!-- ✗ Wrong - unclosed tag -->
<product>
  <id>123</id>
  <title>Product Name

<!-- ✓ Correct -->
<product>
  <id>123</id>
  <title>Product Name</title>
</product>
  1. Ensure proper nesting:
<!-- ✗ Wrong -->
<product>
  <id>123</id>
  <title>Name
  </product>
</title>

<!-- ✓ Correct -->
<product>
  <id>123</id>
  <title>Name</title>
</product>

Event Tracking Debugging

Transaction Not Recorded

Symptoms:

  • Purchases not showing in Criteo reports
  • Conversion tracking incomplete

Diagnosis:

// Check transaction event on confirmation page
console.log(window.criteo_q);

// Look for trackTransaction event:
// {
//   event: "trackTransaction",
//   id: "ORDER123",
//   item: [
//     { id: "PROD1", price: 49.99, quantity: 1 },
//     { id: "PROD2", price: 29.99, quantity: 2 }
//   ]
// }

Solutions:

  1. Verify transaction event fires on order confirmation page only
  2. Check transaction ID format:
// ✗ Wrong - missing transaction details
window.criteo_q.push({
  event: "trackTransaction",
  id: "12345"
});

// ✓ Correct
window.criteo_q.push({
  event: "trackTransaction",
  id: "ORD-12345",
  item: [
    { id: "PROD123", price: 99.99, quantity: 1 },
    { id: "PROD456", price: 49.99, quantity: 2 }
  ]
});
  1. Ensure transaction fires only once:
// Prevent duplicate firing
if (!sessionStorage.getItem('criteo_transaction_fired')) {
  window.criteo_q.push({
    event: "trackTransaction",
    id: orderData.transactionId,
    item: orderData.items
  });
  sessionStorage.setItem('criteo_transaction_fired', 'true');
}

User Email Not Capturing

Symptoms:

  • Email-based retargeting not working
  • Audience sizes lower than expected

Diagnosis:

// Check email event
window.criteo_q.forEach(event => {
  if (event.event === 'setEmail' || event.event === 'setHashedEmail') {
    console.log('Email event:', event);
  }
});

Solutions:

  1. Hash emails client-side for privacy:
async function hashEmail(email) {
  const normalized = email.toLowerCase().trim();
  const msgBuffer = new TextEncoder().encode(normalized);
  const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

// Usage
const userEmail = 'User@Example.com';
const hashedEmail = await hashEmail(userEmail);

window.criteo_q.push({
  event: "setHashedEmail",
  email: hashedEmail
});
  1. Set email on all page types:
// Set email when available (logged-in users)
if (typeof userEmail !== 'undefined' && userEmail) {
  window.criteo_q.push({
    event: "setEmail",
    email: userEmail,
    hash_method: "sha256"
  });
}

Browser Console Debugging

Enable Criteo Debug Mode

// Add debug parameter to see detailed logs
window.criteo_q.push({
  event: "setAccount",
  account: 12345,
  debug: true
});

// Monitor Criteo requests
window.criteo_q.push({
  event: "debug",
  enabled: true
});

Network Tab Analysis

What to Check:

  1. OneTag Script Load

    • URL: https://dynamic.criteo.com/js/ld/ld.js
    • Status: 200 OK
    • Type: script
  2. Event Beacon Requests

    • URL: https://sslwidget.criteo.com/*
    • Status: 200 OK or 204 No Content
    • Type: xhr or img
  3. User Sync Requests

    • URL: https://gum.criteo.com/syncframe
    • Status: 200 OK

Common Network Issues:

// Issue: CORS errors
// Solution: Criteo handles CORS, but verify no proxy is interfering

// Issue: 403 Forbidden
// Possible cause: Invalid account ID or disabled account
// Check account status in Criteo Management Center

// Issue: Request blocked
// Possible cause: Ad blocker
// Test in incognito mode with ad blockers disabled

Console Error Messages

"Criteo account not set"

// ✗ Wrong - account event missing or after other events
window.criteo_q.push({ event: "viewItem", item: "123" });
window.criteo_q.push({ event: "setAccount", account: 12345 });

// ✓ Correct - account must be first
window.criteo_q.push({ event: "setAccount", account: 12345 });
window.criteo_q.push({ event: "setSiteType", type: "d" });
window.criteo_q.push({ event: "viewItem", item: "123" });

"Invalid event format"

// ✗ Wrong
window.criteo_q.push({
  event: "viewItem",
  productId: "123" // incorrect parameter name
});

// ✓ Correct
window.criteo_q.push({
  event: "viewItem",
  item: "123" // correct parameter name
});

Tag Manager Debugging

Google Tag Manager Issues

Preview Mode Testing:

  1. Enable GTM Preview mode
  2. Navigate through site
  3. Check Criteo tags fire on correct triggers
  4. Verify data layer variables populate correctly

Common GTM Issues:

// Issue: Race condition - data layer not ready
// Solution: Use Custom Event trigger

// ✗ Wrong - fires before data layer populates
dataLayer.push({
  event: 'pageview',
  productId: getProductId() // async function
});

// ✓ Correct - wait for data
async function pushCriteoEvent() {
  const productId = await getProductId();
  dataLayer.push({
    event: 'criteo_ready',
    productId: productId
  });
}

Debugging GTM Variables:

// Check GTM variables in console
google_tag_manager['GTM-XXXXX'].dataLayer.get('criteo_account_id');
google_tag_manager['GTM-XXXXX'].dataLayer.get('productId');

Adobe Launch Debugging

Enable debug mode:

// In console
_satellite.setDebug(true);

// Check rule firing
_satellite.track('criteo_product_view');

Performance Issues

Slow Page Load Times

Diagnosis:

// Measure OneTag impact
performance.mark('criteo-start');
// OneTag loads here
performance.mark('criteo-end');
performance.measure('criteo-load', 'criteo-start', 'criteo-end');

const measure = performance.getEntriesByName('criteo-load')[0];
console.log(`Criteo load time: ${measure.duration}ms`);

Solutions:

  1. Ensure async loading:
<!-- ✓ Correct - async loading -->
<script type="text/javascript" src="//dynamic.criteo.com/js/ld/ld.js" async="true"></script>

<!-- ✗ Wrong - synchronous blocking -->
<script type="text/javascript" src="//dynamic.criteo.com/js/ld/ld.js"></script>
  1. Load OneTag after critical content:
<script>
  // Load Criteo after page is interactive
  if (document.readyState === 'complete') {
    loadCriteoTag();
  } else {
    window.addEventListener('load', loadCriteoTag);
  }

  function loadCriteoTag() {
    const script = document.createElement('script');
    script.src = '//dynamic.criteo.com/js/ld/ld.js';
    script.async = true;
    document.head.appendChild(script);
  }
</script>

Data Discrepancies

Conversion Count Mismatches

Common Causes:

  1. Duplicate Transactions - Transaction event fires multiple times
  2. Missing Deduplication - No order ID tracking
  3. Time Zone Differences - Criteo vs. analytics platform time zones
  4. Attribution Models - Different attribution windows

Solutions:

  1. Implement transaction deduplication:
const firedTransactions = new Set();

function trackTransaction(orderId, items) {
  if (firedTransactions.has(orderId)) {
    console.log('Transaction already tracked:', orderId);
    return;
  }

  window.criteo_q.push({
    event: "trackTransaction",
    id: orderId,
    item: items
  });

  firedTransactions.add(orderId);
  sessionStorage.setItem('criteo_transactions',
    JSON.stringify([...firedTransactions]));
}
  1. Use consistent order IDs across platforms

Product View Count Discrepancies

Investigation Steps:

  1. Check if viewItem fires on all product page variants
  2. Verify product IDs match feed IDs exactly
  3. Ensure events don't fire on category pages
// Verify product ID consistency
const feedProductId = "PROD123";
const criteoEventProductId = "PROD123"; // Must match exactly

// ✗ Wrong - IDs don't match
// Feed: "PROD123"
// Event: "prod-123" or "123"

Testing Tools

Criteo OneTag Tester Extension

Use browser extensions for real-time debugging:

  • Criteo OneTag Checker (Chrome/Firefox)
  • Shows active OneTag events
  • Validates event format
  • Displays account configuration

Feed Validator Tools

# Validate feed locally
python3 validate_criteo_feed.py products.xml

# Online validation
# Use Criteo's feed validation tool in Management Center
# Settings > Catalog > Feed Health

cURL Testing

# Test feed accessibility
curl -I -L https://example.com/feeds/products.xml

# Download and inspect feed
curl -o feed.xml https://example.com/feeds/products.xml

# Test with Criteo user agent
curl -A "Criteo/1.0" https://example.com/feeds/products.xml

Best Practices for Prevention

  1. Implement Comprehensive Testing

    • Test OneTag in staging before production
    • Validate feed in test environment
    • Use automated monitoring
  2. Monitor Feed Health

    • Set up alerts for feed failures
    • Check feed processing status daily
    • Review error reports in Criteo dashboard
  3. Version Control

    • Track OneTag changes in version control
    • Document customizations
    • Maintain rollback capability
  4. Regular Audits

    • Monthly OneTag verification
    • Quarterly feed quality reviews
    • Annual implementation audits
  5. Documentation

    • Maintain implementation documentation
    • Document customizations and edge cases
    • Keep troubleshooting runbook updated

Getting Help

Criteo Support Resources

  1. Criteo Help Center: https://help.criteo.com
  2. Technical Documentation: https://help.criteo.com/kb/guide/en/all-criteo-onetag-events
  3. Support Ticket: Submit via Criteo Management Center
  4. Account Manager: Contact for account-specific issues

Information to Provide

When contacting support, include:

  • Account ID
  • Affected page URLs
  • Browser console errors
  • Network tab screenshots
  • Feed URL (if feed-related)
  • Steps to reproduce issue

Next Steps

// SYS.FOOTER