Taboola Data Layer Setup | Blue Frog Docs

Taboola Data Layer Setup

Configure event parameters and data structures for accurate Taboola tracking and conversion optimization.

This guide covers setting up a proper data layer structure for Taboola event tracking, including event parameters, data formatting, and best practices.

Data Layer Overview

A data layer provides a structured way to store and pass information to the Taboola Pixel. It ensures:

  • Consistent data formatting across pages
  • Clean separation of data from tracking code
  • Easy maintenance and updates
  • Reliable event tracking

Basic Data Layer Structure

Simple Data Layer

window.taboolaData = {
  accountId: 1234567,
  pageType: 'product',
  productId: 'PROD_123',
  productPrice: 99.99,
  currency: 'USD'
};

Comprehensive Data Layer

window.taboolaData = {
  // Account configuration
  accountId: 1234567,

  // Page information
  page: {
    type: 'product', // home, category, product, cart, checkout, confirmation
    url: window.location.href,
    title: document.title,
    referrer: document.referrer
  },

  // Product information (e-commerce)
  product: {
    id: 'PROD_123',
    name: 'Wireless Headphones',
    price: 99.99,
    category: 'Electronics > Audio',
    brand: 'AudioBrand',
    availability: 'in stock'
  },

  // User information
  user: {
    id: 'USER_789',
    status: 'logged_in', // logged_in, guest
    type: 'returning' // new, returning
  },

  // Transaction information (confirmation page)
  transaction: {
    id: 'ORDER_12345',
    total: 199.98,
    subtotal: 189.99,
    tax: 9.99,
    shipping: 10.00,
    currency: 'USD',
    items: [
      {
        id: 'PROD_123',
        name: 'Wireless Headphones',
        price: 99.99,
        quantity: 2
      }
    ]
  }
};

Event-Specific Data Layers

Product Page Data Layer

window.taboolaData = {
  accountId: 1234567,
  page: {
    type: 'product'
  },
  product: {
    id: 'SHOE_BLK_10',
    name: 'Running Shoes - Black',
    price: 79.99,
    originalPrice: 99.99, // If on sale
    category: 'Shoes > Running',
    brand: 'Nike',
    availability: 'in stock',
    imageUrl: 'https://example.com/images/shoe.jpg',
    sku: 'SKU_789'
  }
};

// Track product view
window._tfa = window._tfa || [];
window._tfa.push({
  notify: 'event',
  name: 'view_content',
  id: window.taboolaData.accountId,
  content_id: window.taboolaData.product.id,
  content_type: 'product',
  value: window.taboolaData.product.price
});

Shopping Cart Data Layer

window.taboolaData = {
  accountId: 1234567,
  page: {
    type: 'cart'
  },
  cart: {
    items: [
      {
        id: 'PROD_123',
        name: 'Wireless Headphones',
        price: 99.99,
        quantity: 1
      },
      {
        id: 'PROD_456',
        name: 'Phone Case',
        price: 19.99,
        quantity: 2
      }
    ],
    subtotal: 139.97,
    itemCount: 3
  }
};

// Track add to cart
function trackAddToCart(productId, price) {
  window._tfa.push({
    notify: 'event',
    name: 'add_to_cart',
    id: window.taboolaData.accountId,
    content_id: productId,
    value: price,
    currency: 'USD'
  });
}

Order Confirmation Data Layer

window.taboolaData = {
  accountId: 1234567,
  page: {
    type: 'confirmation'
  },
  transaction: {
    id: 'ORDER_2024_001234',
    total: 159.97,
    subtotal: 139.97,
    tax: 10.00,
    shipping: 10.00,
    currency: 'USD',
    items: [
      {
        id: 'PROD_123',
        name: 'Wireless Headphones',
        price: 99.99,
        quantity: 1,
        category: 'Electronics'
      },
      {
        id: 'PROD_456',
        name: 'Phone Case',
        price: 19.99,
        quantity: 2,
        category: 'Accessories'
      }
    ],
    paymentMethod: 'credit_card',
    shippingMethod: 'standard'
  }
};

// Track purchase
window._tfa = window._tfa || [];
window._tfa.push({
  notify: 'event',
  name: 'make_purchase',
  id: window.taboolaData.accountId,
  revenue: window.taboolaData.transaction.total,
  currency: window.taboolaData.transaction.currency,
  order_id: window.taboolaData.transaction.id
});

Content Publisher Data Layer

Article Page

window.taboolaData = {
  accountId: 1234567,
  page: {
    type: 'article'
  },
  content: {
    id: 'ARTICLE_789',
    title: 'How to Choose Running Shoes',
    category: 'Sports > Running',
    author: 'John Doe',
    publishDate: '2024-01-15',
    wordCount: 1500,
    tags: ['running', 'fitness', 'shoes']
  }
};

// Track article view
window._tfa.push({
  notify: 'event',
  name: 'view_content',
  id: window.taboolaData.accountId,
  content_id: window.taboolaData.content.id,
  content_type: 'article'
});

Video Page

window.taboolaData = {
  accountId: 1234567,
  page: {
    type: 'video'
  },
  video: {
    id: 'VIDEO_456',
    title: 'Product Demo - Wireless Headphones',
    duration: 180, // seconds
    category: 'Product Reviews',
    publishDate: '2024-01-20'
  }
};

// Track video view
window._tfa.push({
  notify: 'event',
  name: 'view_content',
  id: window.taboolaData.accountId,
  content_id: window.taboolaData.video.id,
  content_type: 'video'
});

Data Layer Helper Functions

Initialize Data Layer

// Initialize data layer on page load
(function() {
  window.taboolaData = window.taboolaData || {};

  // Set defaults
  window.taboolaData.accountId = window.taboolaData.accountId || 1234567;
  window.taboolaData.page = window.taboolaData.page || {};
  window.taboolaData.page.url = window.location.href;
  window.taboolaData.page.title = document.title;
  window.taboolaData.page.referrer = document.referrer;
})();

Get Data Layer Value

function getTaboolaData(path, defaultValue = null) {
  const keys = path.split('.');
  let value = window.taboolaData;

  for (const key of keys) {
    if (value && typeof value === 'object' && key in value) {
      value = value[key];
    } else {
      return defaultValue;
    }
  }

  return value;
}

// Usage
const productId = getTaboolaData('product.id');
const pageType = getTaboolaData('page.type', 'unknown');
const revenue = getTaboolaData('transaction.total', 0);

Set Data Layer Value

function setTaboolaData(path, value) {
  const keys = path.split('.');
  let obj = window.taboolaData;

  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];
    if (!(key in obj) || typeof obj[key] !== 'object') {
      obj[key] = {};
    }
    obj = obj[key];
  }

  obj[keys[keys.length - 1]] = value;
}

// Usage
setTaboolaData('product.id', 'PROD_789');
setTaboolaData('user.id', 'USER_123');

Dynamic Data Layer Updates

Update on User Action

// Add to cart button click
document.querySelectorAll('.add-to-cart').forEach(button => {
  button.addEventListener('click', function() {
    const productId = this.dataset.productId;
    const productPrice = parseFloat(this.dataset.productPrice);

    // Update data layer
    if (!window.taboolaData.cart) {
      window.taboolaData.cart = { items: [] };
    }

    window.taboolaData.cart.items.push({
      id: productId,
      price: productPrice,
      quantity: 1
    });

    // Track event
    window._tfa.push({
      notify: 'event',
      name: 'add_to_cart',
      id: window.taboolaData.accountId,
      content_id: productId,
      value: productPrice,
      currency: 'USD'
    });
  });
});

Single Page Application Updates

// Update data layer on route change
function updateDataLayerOnRouteChange(newRoute) {
  // Clear previous page data
  window.taboolaData.page = {};
  window.taboolaData.product = {};
  window.taboolaData.content = {};

  // Set new page data
  window.taboolaData.page.type = determinePageType(newRoute);
  window.taboolaData.page.url = newRoute;

  // Track page view
  window._tfa.push({
    notify: 'event',
    name: 'page_view',
    id: window.taboolaData.accountId
  });
}

function determinePageType(url) {
  if (url.includes('/product/')) return 'product';
  if (url.includes('/cart')) return 'cart';
  if (url.includes('/checkout')) return 'checkout';
  if (url.includes('/order-confirmation')) return 'confirmation';
  return 'page';
}

Server-Side Data Layer Generation

PHP Example

<?php
// Generate data layer from server-side data
$product = getProduct($productId);
?>

<script>
window.taboolaData = {
  accountId: <?php echo TABOOLA_ACCOUNT_ID; ?>,
  page: {
    type: 'product'
  },
  product: {
    id: '<?php echo htmlspecialchars($product['id']); ?>',
    name: '<?php echo htmlspecialchars($product['name']); ?>',
    price: <?php echo floatval($product['price']); ?>,
    category: '<?php echo htmlspecialchars($product['category']); ?>',
    brand: '<?php echo htmlspecialchars($product['brand']); ?>',
    availability: '<?php echo $product['in_stock'] ? 'in stock' : 'out of stock'; ?>'
  }
};
</script>

Node.js/Express Example

// Express route
app.get('/product/:id', async (req, res) => {
  const product = await getProduct(req.params.id);

  const taboolaData = {
    accountId: process.env.TABOOLA_ACCOUNT_ID,
    page: {
      type: 'product'
    },
    product: {
      id: product.id,
      name: product.name,
      price: product.price,
      category: product.category,
      brand: product.brand,
      availability: product.inStock ? 'in stock' : 'out of stock'
    }
  };

  res.render('product', {
    product,
    taboolaData: JSON.stringify(taboolaData)
  });
});

// In template
<script>
  window.taboolaData = {{{taboolaData}}};
</script>

Data Validation

Validate Data Before Tracking

function validatePurchaseData(data) {
  const errors = [];

  if (!data.order_id) {
    errors.push('Missing order_id');
  }

  if (typeof data.revenue !== 'number' || data.revenue <= 0) {
    errors.push('Invalid revenue value');
  }

  if (!data.currency || !/^[A-Z]{3}$/.test(data.currency)) {
    errors.push('Invalid currency code');
  }

  return {
    valid: errors.length === 0,
    errors: errors
  };
}

// Usage
function trackPurchase() {
  const purchaseData = {
    order_id: window.taboolaData.transaction.id,
    revenue: window.taboolaData.transaction.total,
    currency: window.taboolaData.transaction.currency
  };

  const validation = validatePurchaseData(purchaseData);

  if (!validation.valid) {
    console.error('Purchase tracking validation failed:', validation.errors);
    return;
  }

  window._tfa.push({
    notify: 'event',
    name: 'make_purchase',
    id: window.taboolaData.accountId,
    ...purchaseData
  });
}

Data Type Conversion

function sanitizeTaboolaData(data) {
  return {
    accountId: parseInt(data.accountId),
    revenue: parseFloat(data.revenue),
    currency: String(data.currency).toUpperCase(),
    order_id: String(data.order_id),
    value: data.value ? parseFloat(data.value) : undefined
  };
}

// Usage
const rawData = {
  accountId: "1234567",
  revenue: "99.99",
  currency: "usd",
  order_id: 12345
};

const cleanData = sanitizeTaboolaData(rawData);
// {
//   accountId: 1234567,
//   revenue: 99.99,
//   currency: "USD",
//   order_id: "12345"
// }

Google Tag Manager Integration

GTM Data Layer to Taboola

// Listen to GTM data layer
window.dataLayer = window.dataLayer || [];
window.dataLayer.push = function(...args) {
  Array.prototype.push.apply(this, args);

  // Process each pushed item
  args.forEach(item => {
    // Purchase event
    if (item.event === 'purchase') {
      window._tfa.push({
        notify: 'event',
        name: 'make_purchase',
        id: 1234567,
        revenue: item.ecommerce.purchase.actionField.revenue,
        currency: item.ecommerce.currencyCode,
        order_id: item.ecommerce.purchase.actionField.id
      });
    }

    // Add to cart event
    if (item.event === 'addToCart') {
      const product = item.ecommerce.add.products[0];
      window._tfa.push({
        notify: 'event',
        name: 'add_to_cart',
        id: 1234567,
        content_id: product.id,
        value: product.price,
        currency: item.ecommerce.currencyCode
      });
    }
  });
};

Best Practices

1. Consistent Structure

Use the same data layer structure across all pages:

// Define standard structure
const TABOOLA_DATA_TEMPLATE = {
  accountId: null,
  page: {
    type: null,
    url: null,
    title: null
  },
  product: null,
  content: null,
  transaction: null,
  user: null
};

// Initialize with template
window.taboolaData = Object.assign({}, TABOOLA_DATA_TEMPLATE, {
  accountId: 1234567
});

2. Data Privacy

Hash personal information:

async function hashEmail(email) {
  const msgBuffer = new TextEncoder().encode(email.toLowerCase().trim());
  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('');
}

// Store hashed data
window.taboolaData.user = {
  id: await hashEmail(userEmail),
  status: 'logged_in'
};

3. Data Layer Loading Order

Ensure data layer loads before tracking:

<!-- 1. Initialize data layer -->
<script>
  window.taboolaData = {
    accountId: 1234567,
    page: { type: 'product' },
    product: { id: 'PROD_123', price: 99.99 }
  };
</script>

<!-- 2. Load Taboola Pixel -->
<script src="//cdn.taboola.com/libtrc/unip/1234567/tfa.js" async></script>

<!-- 3. Track events -->
<script>
  window._tfa = window._tfa || [];
  window._tfa.push({
    notify: 'event',
    name: 'view_content',
    id: window.taboolaData.accountId,
    content_id: window.taboolaData.product.id,
    value: window.taboolaData.product.price
  });
</script>

4. Document Data Layer Schema

/**
 * Taboola Data Layer Schema
 *
 * @typedef {Object} TaboolaData
 * @property {number} accountId - Taboola account ID
 * @property {Object} page - Page information
 * @property {string} page.type - Page type (product, cart, checkout, etc.)
 * @property {Object} [product] - Product information (for product pages)
 * @property {string} product.id - Product ID
 * @property {number} product.price - Product price
 * @property {Object} [transaction] - Transaction information (for confirmation pages)
 * @property {string} transaction.id - Order ID
 * @property {number} transaction.total - Order total
 * @property {string} transaction.currency - Currency code
 */

Debugging Data Layer

Console Inspection

// View current data layer
console.log('Taboola Data Layer:', window.taboolaData);

// View specific values
console.log('Product ID:', window.taboolaData?.product?.id);
console.log('Page Type:', window.taboolaData?.page?.type);
console.log('Transaction Total:', window.taboolaData?.transaction?.total);

Data Layer Monitor

// Monitor data layer changes
const taboolaDataProxy = new Proxy(window.taboolaData, {
  set(target, property, value) {
    console.log(`Data layer updated: ${property} =`, value);
    target[property] = value;
    return true;
  }
});

window.taboolaData = taboolaDataProxy;

Next Steps

// SYS.FOOTER