Microsoft Advertising Data Layer Setup | OpsBlu Docs

Microsoft Advertising Data Layer Setup

Configure data layer for dynamic revenue tracking, custom parameters, and enhanced e-commerce with Microsoft Advertising UET.

Overview

Data layer setup enables Microsoft Advertising UET tag to access dynamic values like transaction revenue, product details, and custom parameters. This is essential for accurate ROAS tracking and automated bidding strategies.

Data Layer Architecture

What is a Data Layer?

A data layer is a JavaScript object that stores structured information about page content, user actions, and transactions. UET tag reads from this data layer to capture dynamic conversion values.

Two Common Approaches

  1. Google Tag Manager Data Layer - Standard dataLayer object
  2. Custom Data Layer - Application-specific JavaScript object

Both can be used with Microsoft Advertising UET tag.

E-commerce Data Layer Implementation

Basic Transaction Data

Step 1: Define Data Layer Structure

Place this before the UET tag on your order confirmation page:

// Define data layer object with order details
var transactionData = {
  orderId: 'ORD-12345',
  total: 149.99,
  currency: 'USD',
  tax: 12.00,
  shipping: 8.00,
  items: [
    {
      productId: 'SKU-001',
      productName: 'Blue Widget',
      category: 'Widgets',
      price: 49.99,
      quantity: 2
    },
    {
      productId: 'SKU-002',
      productName: 'Red Gadget',
      category: 'Gadgets',
      price: 50.01,
      quantity: 1
    }
  ]
};

Step 2: Send to UET

// Fire purchase event with revenue data
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': transactionData.total,
  'currency': transactionData.currency
});

Enhanced E-commerce Tracking

For dynamic remarketing and Shopping campaigns:

// On product detail page
var productData = {
  id: 'SKU-001',
  name: 'Blue Widget',
  category: 'Widgets/Blue',
  price: 49.99
};

window.uetq = window.uetq || [];
window.uetq.push('event', '', {
  'ecomm_prodid': productData.id,
  'ecomm_pagetype': 'product',
  'ecomm_totalvalue': productData.price
});

E-commerce Page Types

Page Type ecomm_pagetype Value When to Use
Homepage home Site homepage
Category category Product category/listing pages
Product product Individual product detail pages
Cart cart Shopping cart page
Purchase purchase Order confirmation page
Other other All other pages

Product Data Parameters

// Complete e-commerce data layer
window.uetq = window.uetq || [];
window.uetq.push('event', '', {
  'ecomm_prodid': 'SKU-001',           // Product ID (required)
  'ecomm_pagetype': 'product',         // Page type (required)
  'ecomm_totalvalue': 49.99,           // Product price (required)
  'ecomm_category': 'Widgets > Blue'   // Product category (optional)
});

For multiple products (cart, purchase pages):

window.uetq = window.uetq || [];
window.uetq.push('event', '', {
  'ecomm_prodid': ['SKU-001', 'SKU-002', 'SKU-003'],
  'ecomm_pagetype': 'cart',
  'ecomm_totalvalue': 149.99
});

Google Tag Manager Integration

GTM Data Layer Setup

Step 1: Push Data to GTM Data Layer

On your confirmation page, before GTM container:

dataLayer.push({
  'event': 'transaction',
  'transactionId': 'ORD-12345',
  'transactionTotal': 149.99,
  'transactionTax': 12.00,
  'transactionShipping': 8.00,
  'transactionCurrency': 'USD',
  'transactionProducts': [
    {
      'sku': 'SKU-001',
      'name': 'Blue Widget',
      'category': 'Widgets',
      'price': 49.99,
      'quantity': 2
    }
  ]
});

Step 2: Create GTM Variables

Create Data Layer Variables in GTM:

Variable: Transaction Total

  • Variable Type: Data Layer Variable
  • Data Layer Variable Name: transactionTotal
  • Variable Name: DLV - Transaction Total

Variable: Transaction Currency

  • Variable Type: Data Layer Variable
  • Data Layer Variable Name: transactionCurrency
  • Variable Name: DLV - Transaction Currency

Variable: Transaction ID

  • Variable Type: Data Layer Variable
  • Data Layer Variable Name: transactionId
  • Variable Name: DLV - Transaction ID

Step 3: Create UET Conversion Tag

Tag Configuration:

Tag Type: Custom HTML

<script>
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': {{DLV - Transaction Total}},
  'currency': {{DLV - Transaction Currency}}
});
</script>

Trigger: Custom Event = transaction

Dynamic Remarketing with GTM

Create separate tags for each page type:

Product Page Tag

Custom HTML:

<script>
window.uetq = window.uetq || [];
window.uetq.push('event', '', {
  'ecomm_prodid': {{DLV - Product ID}},
  'ecomm_pagetype': 'product',
  'ecomm_totalvalue': {{DLV - Product Price}}
});
</script>

Trigger: Page View on product pages

Cart Page Tag

Custom HTML:

<script>
window.uetq = window.uetq || [];
window.uetq.push('event', '', {
  'ecomm_prodid': {{DLV - Cart Product IDs}},
  'ecomm_pagetype': 'cart',
  'ecomm_totalvalue': {{DLV - Cart Total}}
});
</script>

Trigger: Page View on cart page

Server-Side Rendered Data Layer

PHP Example

For PHP-based e-commerce platforms:

<!-- Order confirmation page -->
<script>
// Server-side data rendered into JavaScript
var orderData = {
  orderId: '<?php echo htmlspecialchars($order->id); ?>',
  total: <?php echo number_format($order->total, 2, '.', ''); ?>,
  currency: '<?php echo htmlspecialchars($order->currency); ?>',
  items: <?php echo json_encode($order->items); ?>
};

// Fire UET conversion event
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': orderData.total,
  'currency': orderData.currency
});
</script>

Node.js / Express Example

For server-side JavaScript frameworks:

// Route handler
app.get('/thank-you', (req, res) => {
  const order = getOrderFromDatabase(req.query.orderId);

  res.render('thank-you', {
    orderId: order.id,
    total: order.total,
    currency: order.currency,
    items: order.items
  });
});

Template (EJS, Handlebars, etc.):

<script>
var orderData = {
  orderId: '<%= orderId %>',
  total: <%= total %>,
  currency: '<%= currency %>',
  items: <%- JSON.stringify(items) %>
};

window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': orderData.total,
  'currency': orderData.currency
});
</script>

Python / Django Example

# views.py
def thank_you(request, order_id):
    order = Order.objects.get(id=order_id)
    context = {
        'order_id': order.id,
        'order_total': order.total,
        'order_currency': order.currency,
        'order_items': order.items.all()
    }
    return render(request, 'thank_you.html', context)

Template:

<script>
var orderData = {
  orderId: '{{ order_id }}',
  total: {{ order_total }},
  currency: '{{ order_currency }}'
};

window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': orderData.total,
  'currency': orderData.currency
});
</script>

Single Page Application (SPA) Data Layer

React Example

// OrderConfirmation.jsx
import { useEffect } from 'react';

function OrderConfirmation({ order }) {
  useEffect(() => {
    // Fire UET conversion when component mounts
    if (window.uetq && order) {
      window.uetq = window.uetq || [];
      window.uetq.push('event', 'purchase', {
        'revenue_value': order.total,
        'currency': order.currency
      });
    }
  }, [order]);

  return (
    <div>
      <h1>Thank you for your order!</h1>
      <p>Order ID: {order.id}</p>
      <p>Total: {order.currency} {order.total}</p>
    </div>
  );
}

Vue.js Example

// OrderConfirmation.vue
<template>
  <div>
    <h1>Thank you for your order!</h1>
    <p>Order ID: {{ order.id }}</p>
    <p>Total: {{ order.currency }} {{ order.total }}</p>
  </div>
</template>

<script>
export default {
  name: 'OrderConfirmation',
  props: ['order'],
  mounted() {
    // Fire UET conversion on component mount
    if (window.uetq && this.order) {
      window.uetq = window.uetq || [];
      window.uetq.push('event', 'purchase', {
        'revenue_value': this.order.total,
        'currency': this.order.currency
      });
    }
  }
}
</script>

Angular Example

// order-confirmation.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

declare global {
  interface Window {
    uetq: any[];
  }
}

@Component({
  selector: 'app-order-confirmation',
  templateUrl: './order-confirmation.component.html'
})
export class OrderConfirmationComponent implements OnInit {
  order: any;

  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    this.route.data.subscribe(data => {
      this.order = data.order;
      this.fireConversion();
    });
  }

  fireConversion() {
    if (this.order) {
      window.uetq = window.uetq || [];
      window.uetq.push('event', 'purchase', {
        'revenue_value': this.order.total,
        'currency': this.order.currency
      });
    }
  }
}

Custom Parameters

Variable Revenue Values

Track different conversion values:

// Lead value varies by source
var leadValue;
if (userSource === 'organic') {
  leadValue = 50;
} else if (userSource === 'paid') {
  leadValue = 75;
} else {
  leadValue = 25;
}

window.uetq = window.uetq || [];
window.uetq.push('event', 'lead', {
  'event_value': leadValue,
  'event_label': userSource
});

Product Categories

Track conversions by product category:

var productCategory = 'Electronics > Headphones';

window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': 199.99,
  'currency': 'USD',
  'event_category': productCategory
});

User Segments

Pass user segment data for analysis:

var userSegment = isPremiumCustomer ? 'premium' : 'standard';

window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': orderTotal,
  'currency': 'USD',
  'event_label': userSegment
});

Data Validation

Validate Before Sending

Always validate data exists and is correct type:

// Defensive programming
function fireUETConversion(orderData) {
  // Validate required fields exist
  if (!orderData || !orderData.total || !orderData.currency) {
    console.error('UET: Missing required order data');
    return;
  }

  // Validate total is a number
  var total = parseFloat(orderData.total);
  if (isNaN(total) || total <= 0) {
    console.error('UET: Invalid order total');
    return;
  }

  // Validate currency code
  var validCurrencies = ['USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY'];
  if (!validCurrencies.includes(orderData.currency)) {
    console.warn('UET: Unexpected currency code');
  }

  // Fire conversion
  window.uetq = window.uetq || [];
  window.uetq.push('event', 'purchase', {
    'revenue_value': total,
    'currency': orderData.currency
  });
}

// Usage
fireUETConversion(transactionData);

Type Coercion

Ensure correct data types:

// Convert string to number
var orderTotal = '149.99'; // Might come as string from API
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': parseFloat(orderTotal), // Convert to number
  'currency': 'USD'
});

Remove Duplicates

Prevent duplicate conversion fires:

// Use flag to fire conversion only once
if (!sessionStorage.getItem('uet_conversion_fired')) {
  window.uetq = window.uetq || [];
  window.uetq.push('event', 'purchase', {
    'revenue_value': orderTotal,
    'currency': 'USD'
  });
  sessionStorage.setItem('uet_conversion_fired', 'true');
}

Multi-Currency Support

Automatic Currency Conversion

Microsoft Advertising automatically converts revenue to your account currency:

// Customer pays in EUR
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': 89.99,
  'currency': 'EUR' // Automatically converted to account currency
});

Supported Currencies

Microsoft Advertising supports 100+ currencies including:

  • USD (US Dollar)
  • EUR (Euro)
  • GBP (British Pound)
  • CAD (Canadian Dollar)
  • AUD (Australian Dollar)
  • JPY (Japanese Yen)
  • CNY (Chinese Yuan)
  • INR (Indian Rupee)

Full list: Microsoft Advertising Currencies

Platform-Specific Implementations

Shopify

Shopify liquid template on order confirmation page:

<!-- Thank you page -->
<script>
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': {{ checkout.total_price | money_without_currency }},
  'currency': '{{ checkout.currency }}'
});
</script>

WooCommerce (WordPress)

Add to functions.php or custom plugin:

// Add UET conversion to order confirmation
add_action('woocommerce_thankyou', 'uet_conversion_tracking');

function uet_conversion_tracking($order_id) {
  if (!$order_id) return;

  $order = wc_get_order($order_id);
  $order_total = $order->get_total();
  $currency = $order->get_currency();

  ?>
  <script>
  window.uetq = window.uetq || [];
  window.uetq.push('event', 'purchase', {
    'revenue_value': <?php echo $order_total; ?>,
    'currency': '<?php echo $currency; ?>'
  });
  </script>
  <?php
}

Magento 2

Create custom module or add to theme:

<!-- checkout/success.phtml -->
<?php
$order = $block->getOrder();
$orderId = $order->getIncrementId();
$orderTotal = $order->getGrandTotal();
$currency = $order->getOrderCurrencyCode();
?>

<script>
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': <?php echo $orderTotal; ?>,
  'currency': '<?php echo $currency; ?>'
});
</script>

BigCommerce

Add to order confirmation page template:

<script>
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': {{checkout.order_amount}},
  'currency': '{{checkout.currency_code}}'
});
</script>

Debugging Data Layer

Browser Console Testing

Test data layer in browser console:

// Check if UET queue exists
console.log(window.uetq);

// Manually fire test conversion
window.uetq = window.uetq || [];
window.uetq.push('event', 'purchase', {
  'revenue_value': 99.99,
  'currency': 'USD'
});

// Check if event was added
console.log(window.uetq);

GTM Preview Mode

  1. Click Preview in GTM
  2. Navigate to your site
  3. Complete conversion action
  4. Check Variables tab for Data Layer values
  5. Verify UET tag fires with correct values

Network Tab Inspection

  1. Open DevTools > Network tab
  2. Filter by "bat.bing.com"
  3. Complete conversion
  4. Inspect request parameters:
    • gv: Goal value (revenue_value)
    • gc: Goal currency
    • Look for your revenue amount in request

Data Layer Best Practices

1. Load Before UET Tag

Data layer must be defined before UET tag loads:

<!-- CORRECT ORDER -->
<script>
// 1. Define data layer
var transactionData = { total: 99.99, currency: 'USD' };
</script>

<!-- 2. UET base tag loads -->
<script>
(function(w,d,t,r,u){ /* UET tag code */ })(...);
</script>

<!-- 3. Fire conversion event -->
<script>
window.uetq.push('event', 'purchase', {
  'revenue_value': transactionData.total,
  'currency': transactionData.currency
});
</script>

2. Use Consistent Variable Names

Maintain naming conventions across your application:

// Good - consistent naming
var orderData = { total: 99.99 };
var cartData = { total: 49.99 };

// Bad - inconsistent
var orderTotal = 99.99;
var cart_value = 49.99;

3. Document Data Layer Structure

Create documentation for your team:

/**
 * Order Data Layer Structure
 *
 * @property {string} orderId - Unique order identifier
 * @property {number} total - Order total (after tax/shipping)
 * @property {string} currency - 3-letter ISO currency code
 * @property {Array} items - Array of order items
 */
var orderData = {
  orderId: 'ORD-12345',
  total: 149.99,
  currency: 'USD',
  items: []
};

4. Version Control

Track data layer changes in version control:

// v1.0 - Basic transaction tracking
// v1.1 - Added product-level data
// v1.2 - Added user segment information

Data Layer Checklist

  • Data layer defined before UET tag
  • Revenue values are numbers (not strings)
  • Currency codes are valid 3-letter ISO codes
  • Data validated before firing events
  • Test conversions appear with correct revenue in Microsoft Advertising
  • No duplicate conversions firing
  • GTM variables properly configured (if using GTM)
  • SPA conversions fire on route changes (if applicable)
  • Server-side data properly escaped and sanitized
  • Documentation created for data layer structure

Next Steps