Snapchat Ads Troubleshooting and Debugging | Blue Frog Docs

Snapchat Ads Troubleshooting and Debugging

Diagnose and fix issues with Snap Pixel, Conversions API, event tracking, and attribution.

Troubleshooting Overview

This guide helps you diagnose and resolve common issues with Snapchat Ads tracking, from pixel installation problems to attribution discrepancies.

Snap Pixel Issues

Pixel Not Loading

Symptoms

  • Snap Pixel Helper shows no pixel detected
  • No network requests to sc-static.net
  • Events not appearing in Events Manager

Diagnostic Steps

  1. Check Browser Console
// Open DevTools Console (F12)
// Look for JavaScript errors
// Common errors:
// - snaptr is not defined
// - Failed to load resource: sc-static.net
// - Content Security Policy violations
  1. Verify Pixel Code Installation
// In browser console, check if snaptr is loaded:
typeof snaptr
// Should return: "function"

// Check if pixel initialized:
snaptr.queue
// Should return an array
  1. Check Network Tab
  • Open DevTools > Network tab
  • Filter by "sc-static.net"
  • Verify scevent.min.js loads successfully
  • Check for blocked requests

Common Causes & Solutions

Issue Cause Solution
Script blocked Ad blocker or browser extension Test in incognito mode without extensions
CSP violation Content Security Policy blocks external scripts Add sc-static.net to CSP allowlist
Incorrect pixel ID Wrong pixel ID in code Verify pixel ID in Ads Manager > Events Manager
Script not in <head> Pixel code placed in wrong location Move to <head> section before closing tag
Syntax error Malformed JavaScript Copy fresh code from Events Manager

Solution: Fix Pixel Loading

<!-- Correct placement: Inside <head> tag -->
<head>
  <meta charset="UTF-8">
  <title>Page Title</title>

  <!-- Snap Pixel Code - Place BEFORE closing </head> -->
  <script type='text/javascript'>
  (function(e,t,n){if(e.snaptr)return;var a=e.snaptr=function()
  {a.handleRequest?a.handleRequest.apply(a,arguments):a.queue.push(arguments)};
  a.queue=[];var s='script';var r=t.createElement(s);r.async=!0;
  r.src=n;var u=t.getElementsByTagName(s)[0];
  u.parentNode.insertBefore(r,u);})(window,document,
  'https://sc-static.net/scevent.min.js');

  snaptr('init', 'YOUR_ACTUAL_PIXEL_ID');
  snaptr('track', 'PAGE_VIEW');
  </script>
</head>

Events Not Firing

Symptoms

  • Pixel loads but specific events don't appear
  • Test Events tool shows no events
  • Events appear with delay or inconsistently

Diagnostic Steps

  1. Use Snap Pixel Helper

  2. Check Event Syntax

// CORRECT: Standard event names
snaptr('track', 'PURCHASE');  // Uppercase
snaptr('track', 'ADD_CART');
snaptr('track', 'VIEW_CONTENT');

// INCORRECT: Wrong case or spelling
snaptr('track', 'purchase');  // lowercase - won't work
snaptr('track', 'CHECKOUT');  // non-standard event name
snaptr('track', 'AddCart');   // wrong format
  1. Verify Event Parameters
// Check in console before event fires
console.log('Tracking PURCHASE with params:', {
  'price': 99.99,
  'currency': 'USD',
  'transaction_id': 'ORDER_12345'
});

snaptr('track', 'PURCHASE', {
  'price': 99.99,
  'currency': 'USD',
  'transaction_id': 'ORDER_12345'
});

Common Causes & Solutions

Issue Cause Solution
Event fires before pixel loads Race condition Wrap event in pixel ready callback
Wrong event name Typo or non-standard name Use standard event names (uppercase)
Missing parameters Required params not included Include price, currency, item_ids
Event fires multiple times Duplicate event calls Add deduplication logic
SPA navigation issues Events don't fire on route change Fire PAGE_VIEW on route changes

Solution: Event Timing

// Wait for pixel to be ready before firing events
snaptr('init', 'YOUR_PIXEL_ID', {}, function() {
  // Pixel is loaded and ready
  console.log('Snap Pixel ready');
});

// For events triggered by user actions
document.getElementById('checkout-btn').addEventListener('click', function() {
  // Ensure snaptr is defined
  if (typeof snaptr !== 'undefined') {
    snaptr('track', 'START_CHECKOUT', {
      'price': cartTotal,
      'currency': 'USD'
    });
  } else {
    console.error('Snap Pixel not loaded');
  }
});

Advanced Matching Issues

Symptoms

  • Low match rates reported
  • Events not attributing to users
  • Audience sizes smaller than expected

Diagnostic Steps

  1. Verify Hashing Implementation
// Test your hashing function
function testHashing() {
  const testEmail = 'Test@Example.com';
  const hashed = hashSHA256(testEmail);

  // Should be lowercase, trimmed, then hashed
  console.log('Original:', testEmail);
  console.log('Hashed:', hashed);

  // Verify it matches expected format
  // SHA256 should be 64 hex characters
  if (hashed.length !== 64) {
    console.error('Hash length incorrect:', hashed.length);
  }
}
  1. Check User Data Format
// CORRECT: Properly formatted and hashed
snaptr('init', 'YOUR_PIXEL_ID', {
  'user_email': hashSHA256('user@example.com'),  // Hashed
  'user_phone_number': hashSHA256('+15551234567')  // Hashed with country code
});

// INCORRECT: Common mistakes
snaptr('init', 'YOUR_PIXEL_ID', {
  'user_email': 'user@example.com',  // Not hashed
  'user_phone_number': '555-1234'  // Missing country code, not hashed
});

Solution: Correct Hashing

// Use CryptoJS or native crypto
function hashSHA256(data) {
  if (!data) return '';

  // Step 1: Convert to lowercase
  data = data.toLowerCase();

  // Step 2: Trim whitespace
  data = data.trim();

  // Step 3: Hash with SHA256
  if (typeof CryptoJS !== 'undefined') {
    return CryptoJS.SHA256(data).toString();
  } else if (typeof crypto !== 'undefined' && crypto.subtle) {
    // Modern browsers with Web Crypto API
    return crypto.subtle.digest('SHA-256', new TextEncoder().encode(data))
      .then(hash => {
        return Array.from(new Uint8Array(hash))
          .map(b => b.toString(16).padStart(2, '0'))
          .join('');
      });
  }

  console.error('No hashing library available');
  return '';
}

// Initialize with hashed data
snaptr('init', 'YOUR_PIXEL_ID', {
  'user_email': hashSHA256('user@example.com'),
  'user_phone_number': hashSHA256('+15551234567')
});

Conversions API Issues

CAPI Events Not Tracking

Symptoms

  • Server-side events don't appear in Events Manager
  • API returns errors
  • Events appear but don't attribute

Diagnostic Steps

  1. Check API Response
async function debugCAPIEvent(eventData) {
  try {
    const response = await sendSnapEvent(eventData);

    console.log('CAPI Response:', response);

    // Check for errors in response
    if (response.errors) {
      console.error('CAPI Errors:', response.errors);
      response.errors.forEach(error => {
        console.error(`Error: ${error.message}`);
        console.error(`Field: ${error.field}`);
      });
    }

    // Check success
    if (response.data && response.data.success) {
      console.log('Event sent successfully');
    }

    return response;
  } catch (error) {
    console.error('CAPI Request Failed:', error.message);
    console.error('Status:', error.response?.status);
    console.error('Response:', error.response?.data);
  }
}
  1. Validate Payload Structure
// Correct CAPI payload structure
const validPayload = {
  data: [{
    event_type: 'PURCHASE',  // Required: Standard event name
    event_conversion_type: 'WEB',  // Required: WEB, MOBILE_APP, OFFLINE
    event_tag: 'event_tag',  // Required: From Snap Ads Manager
    timestamp: Date.now(),  // Required: Unix timestamp in milliseconds
    hashed_email: hashSHA256(email),  // Recommended
    hashed_phone_number: hashSHA256(phone),  // Recommended
    hashed_ip_address: hashSHA256(ipAddress),  // Recommended
    user_agent: userAgent,  // Recommended
    uuid_c1: snapClickId,  // Recommended: _scid cookie value
    price: '99.99',  // String format
    currency: 'USD',  // ISO 4217 currency code
    transaction_id: orderId,  // For deduplication
    item_ids: ['SKU_123'],  // Array of strings
    page_url: 'https://example.com/confirmation'
  }]
};

Common Errors & Solutions

Error Code Message Solution
401 Unauthorized Verify access token is valid and not expired
400 Invalid event_type Use standard event names (PURCHASE, ADD_CART, etc.)
400 Missing required field Include event_type, event_conversion_type, event_tag, timestamp
400 Invalid timestamp Use milliseconds since epoch (Date.now())
429 Rate limit exceeded Implement exponential backoff retry logic
500 Internal server error Retry request, contact Snapchat support if persistent

Solution: CAPI Error Handling

async function sendSnapEventWithRetry(eventData, maxRetries = 3) {
  let lastError;

  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const payload = {
        data: [{
          event_type: eventData.eventType,
          event_conversion_type: 'WEB',
          event_tag: 'event_tag',
          timestamp: Date.now(),
          hashed_email: eventData.hashedEmail,
          hashed_phone_number: eventData.hashedPhone,
          user_agent: eventData.userAgent,
          hashed_ip_address: eventData.hashedIp,
          uuid_c1: eventData.snapClickId,
          price: String(eventData.price),
          currency: eventData.currency,
          transaction_id: eventData.transactionId,
          item_ids: eventData.itemIds
        }]
      };

      const response = await axios.post(
        'https://tr.snapchat.com/v2/conversion',
        payload,
        {
          headers: {
            'Authorization': `Bearer ${process.env.SNAP_ACCESS_TOKEN}`,
            'Content-Type': 'application/json'
          },
          timeout: 5000  // 5 second timeout
        }
      );

      // Success
      console.log(`CAPI event sent successfully on attempt ${attempt}`);
      return response.data;

    } catch (error) {
      lastError = error;

      // Don't retry on authentication errors
      if (error.response?.status === 401 || error.response?.status === 403) {
        console.error('Authentication error, not retrying');
        throw error;
      }

      // Don't retry on bad request (fix data instead)
      if (error.response?.status === 400) {
        console.error('Bad request:', error.response.data);
        throw error;
      }

      // Retry on server errors or rate limits
      if (attempt < maxRetries) {
        const backoffMs = Math.pow(2, attempt) * 1000;  // Exponential backoff
        console.log(`Retrying in ${backoffMs}ms (attempt ${attempt + 1}/${maxRetries})`);
        await new Promise(resolve => setTimeout(resolve, backoffMs));
      }
    }
  }

  console.error(`Failed after ${maxRetries} attempts`);
  throw lastError;
}

Event Deduplication Issues

Symptoms

  • Events counted twice (pixel + CAPI)
  • Purchase revenue doubled
  • Inflated conversion counts

Diagnostic Steps

  1. Verify Deduplication IDs Match
// Browser-side (Pixel)
const dedupId = `ORDER_${orderId}_${timestamp}`;
console.log('Browser dedup ID:', dedupId);

snaptr('track', 'PURCHASE', {
  'transaction_id': orderId,
  'client_dedup_id': dedupId,  // Critical for deduplication
  'price': 99.99,
  'currency': 'USD'
});

// Server-side (CAPI) - Must use EXACT same ID
console.log('Server dedup ID:', dedupId);

const payload = {
  data: [{
    client_dedup_id: dedupId,  // MUST MATCH browser exactly
    event_type: 'PURCHASE',
    // ... rest of data
  }]
};
  1. Check Event Manager for Duplicates
  • Go to Events Manager > Test Events
  • Send test event from both pixel and CAPI
  • Verify only one event appears
  • Check event details show both sources

Solution: Implement Deduplication

// Generate consistent deduplication ID
function generateDedupId(transactionId) {
  // Use transaction ID + timestamp
  // This must be generated ONCE and shared between browser and server
  const timestamp = Date.now();
  return `${transactionId}_${timestamp}`;
}

// On client-side (when order is placed)
const dedupId = generateDedupId(orderId);

// Store in cookie or send to server
document.cookie = `snap_dedup_id=${dedupId}; path=/; max-age=300`;  // 5 minutes

// Track with pixel
snaptr('track', 'PURCHASE', {
  'transaction_id': orderId,
  'client_dedup_id': dedupId,
  'price': orderTotal,
  'currency': 'USD'
});

// On server-side (when processing order)
// Retrieve dedup ID from cookie or request
const dedupId = req.cookies.snap_dedup_id;

// Send to CAPI with same dedup ID
await sendSnapEvent({
  client_dedup_id: dedupId,  // Same ID as browser
  event_type: 'PURCHASE',
  transaction_id: orderId,
  // ... rest of data
});

Attribution Issues

Conversions Not Attributing to Campaigns

Symptoms

  • Events appear in Events Manager
  • No conversions in campaign reporting
  • Attribution window issues

Diagnostic Steps

  1. Verify Event Configuration

    • Go to Events Manager
    • Select your pixel
    • Click "Set Up Web Events"
    • Verify PURCHASE is configured as a conversion event
  2. Check Attribution Windows

    • Ads Manager > Settings > Attribution
    • Default: 1-day view, 28-day click
    • Verify windows align with your business
  3. Verify User Journey

// Track the user journey
console.log('User clicked ad?', document.cookie.includes('_scid'));
console.log('Snap click ID:', getCookie('_scid'));

function getCookie(name) {
  const value = `; ${document.cookie}`;
  const parts = value.split(`; ${name}=`);
  if (parts.length === 2) return parts.pop().split(';').shift();
}

Common Causes & Solutions

Issue Cause Solution
Event not set as conversion Event not configured in Events Manager Configure event as conversion in Events Manager
Wrong attribution window Event outside attribution window Verify user clicked ad within attribution window
Missing click ID _scid cookie not set or expired Verify pixel loads immediately on landing
Cross-domain tracking issue Cookie lost when changing domains Implement cross-domain tracking
Conversion delay Purchase happens days after click Extend attribution window if appropriate

Solution: Verify Attribution Setup

// On landing page (immediately after ad click)
// Verify Snap click ID is captured
(function checkAttribution() {
  const scid = getCookie('_scid');

  if (scid) {
    console.log('Attribution successful - Click ID:', scid);

    // Store for later use (optional)
    sessionStorage.setItem('snap_click_id', scid);
  } else {
    console.warn('No Snap click ID found - event may not attribute');
  }

  function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
  }
})();

// On conversion page - include click ID in CAPI
const snapClickId = getCookie('_scid') || sessionStorage.getItem('snap_click_id');

await sendSnapEvent({
  uuid_c1: snapClickId,  // Critical for attribution
  event_type: 'PURCHASE',
  // ... rest of data
});

Revenue Discrepancies

Symptoms

  • Revenue in Snapchat doesn't match actual sales
  • Conversion values incorrect
  • Currency conversion issues

Diagnostic Steps

  1. Verify Price Format
// Check what's being sent
const orderTotal = 99.99;

// CORRECT: Number or string
snaptr('track', 'PURCHASE', {
  'price': 99.99,  // Number
  'currency': 'USD'
});

// Or
snaptr('track', 'PURCHASE', {
  'price': '99.99',  // String
  'currency': 'USD'
});

// INCORRECT: Wrong format
snaptr('track', 'PURCHASE', {
  'price': '$99.99',  // Don't include currency symbol
  'currency': 'USD'
});
  1. Check Currency Codes
// Use ISO 4217 currency codes
const validCurrencies = ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY'];

function validateCurrency(currency) {
  if (!validCurrencies.includes(currency)) {
    console.error('Invalid currency code:', currency);
    return false;
  }
  return true;
}
  1. Audit Event Parameters
// Log all purchase events for debugging
const originalTrack = window.snaptr;
window.snaptr = function(method, event, params) {
  if (method === 'track' && event === 'PURCHASE') {
    console.log('PURCHASE Event Debug:', {
      price: params.price,
      currency: params.currency,
      transaction_id: params.transaction_id,
      timestamp: new Date().toISOString()
    });

    // Verify price is numeric
    if (isNaN(parseFloat(params.price))) {
      console.error('Price is not a number:', params.price);
    }
  }

  return originalTrack.apply(this, arguments);
};

Solution: Correct Revenue Tracking

// Calculate order total correctly
function trackPurchase(order) {
  // Ensure numeric value
  const orderTotal = parseFloat(order.total);

  if (isNaN(orderTotal) || orderTotal <= 0) {
    console.error('Invalid order total:', order.total);
    return;
  }

  // Format to 2 decimal places
  const formattedTotal = orderTotal.toFixed(2);

  console.log('Tracking purchase:', {
    total: formattedTotal,
    currency: order.currency,
    orderId: order.id
  });

  snaptr('track', 'PURCHASE', {
    'price': formattedTotal,  // Always use formatted number
    'currency': order.currency.toUpperCase(),  // Uppercase currency code
    'transaction_id': order.id,
    'number_items': order.items.length,
    'item_ids': order.items.map(item => item.sku)
  });
}

Cross-Domain Tracking Issues

Symptoms

  • Users lost when moving between domains
  • Conversions not attributing across domains
  • Multiple sessions for same user

Diagnostic Steps

  1. Check Cookie Domain Settings
// Verify cookie domain configuration
snaptr('init', 'YOUR_PIXEL_ID', {
  'cookie_domain': '.example.com'  // Share across subdomains
});

// Check if cookie is accessible
console.log('Cookies:', document.cookie);
console.log('_scid cookie:', getCookie('_scid'));
  1. Verify Pixel on All Domains
  • Visit each domain in your funnel
  • Check Pixel Helper on each page
  • Verify same pixel ID used everywhere

Solution: Configure Cross-Domain Tracking

See Cross-Domain Tracking Guide for detailed implementation.

Testing & Validation Tools

Snap Pixel Helper

Chrome Extension for debugging pixel implementation:

  • Install from Chrome Web Store
  • Click extension icon on any page
  • Shows: Pixel loaded, events fired, parameters sent
  • Color indicators: Green (good), Yellow (warning), Red (error)

Test Events Tool

Events Manager Feature for testing before launch:

  1. Go to Events Manager
  2. Select your pixel
  3. Click "Test Events" tab
  4. Enter your website URL
  5. Browse your site
  6. Verify events appear in real-time

Browser DevTools

Console Debugging:

// Check if pixel is loaded
typeof snaptr  // Should return 'function'

// Enable debug mode
snaptr('debug', true);

// Check pixel queue
snaptr.queue

// Monitor network requests
// DevTools > Network > Filter: 'sc-static.net'

Network Tab Debugging:

  1. Open DevTools (F12)
  2. Go to Network tab
  3. Filter by "tr.snapchat.com"
  4. Trigger conversion event
  5. Click request to see:
    • Request payload
    • Response status
    • Headers

Manual Testing Checklist

## Pre-Launch Testing Checklist

### Pixel Loading
- [ ] Pixel loads on all page types
- [ ] No JavaScript console errors
- [ ] Network requests succeed
- [ ] Pixel Helper shows green checkmark

### Event Firing
- [ ] PAGE_VIEW fires on all pages
- [ ] VIEW_CONTENT fires on product pages
- [ ] ADD_CART fires when adding to cart
- [ ] START_CHECKOUT fires at checkout
- [ ] PURCHASE fires on confirmation page

### Event Parameters
- [ ] All events include required parameters
- [ ] Price values are numeric
- [ ] Currency codes are valid (ISO 4217)
- [ ] Transaction IDs are unique
- [ ] Item IDs match product catalog

### Advanced Matching
- [ ] Email hashing implemented correctly
- [ ] Phone number hashing implemented
- [ ] Hash format verified (64 char hex)

### Attribution
- [ ] _scid cookie set on ad click
- [ ] Cookie persists through checkout
- [ ] Events appear in Test Events tool
- [ ] Events appear in Events Manager

### CAPI (if implemented)
- [ ] Server events send successfully
- [ ] API returns 200 status
- [ ] Deduplication configured
- [ ] Events appear in Events Manager

### Cross-Browser Testing
- [ ] Chrome (desktop & mobile)
- [ ] Safari (desktop & mobile/iOS)
- [ ] Firefox
- [ ] Edge

### Privacy & Compliance
- [ ] Consent management implemented
- [ ] PII properly hashed
- [ ] Privacy policy updated

Common Error Messages

Error Meaning Solution
"snaptr is not defined" Pixel script not loaded Verify pixel code in <head>, check for JS errors
"Invalid pixel ID" Wrong or malformed pixel ID Copy correct ID from Events Manager
"Event type not recognized" Non-standard event name Use standard events: PURCHASE, ADD_CART, etc.
"Missing required parameter" Event missing required field Include price, currency for commerce events
"Unauthorized" (CAPI) Invalid or expired access token Generate new access token in Business Manager
"Rate limit exceeded" Too many API requests Implement rate limiting, exponential backoff

Getting Additional Help

Snapchat Support Resources

Community Resources

  • Snapchat Ads Community Forum
  • Stack Overflow - Tag: [snapchat-ads]
  • Developer Discord servers
  • Agency partner support

When to Contact Support

Contact Snapchat Support if:

  • Persistent pixel loading issues after troubleshooting
  • API errors not documented
  • Attribution discrepancies after verification
  • Events Manager showing incorrect data
  • Account-level issues or billing questions
// SYS.FOOTER