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
- Google Tag Manager Data Layer - Standard
dataLayerobject - 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
- Click Preview in GTM
- Navigate to your site
- Complete conversion action
- Check Variables tab for Data Layer values
- Verify UET tag fires with correct values
Network Tab Inspection
- Open DevTools > Network tab
- Filter by "bat.bing.com"
- Complete conversion
- 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
- Implement cross-domain tracking for multi-domain conversions
- Explore server-side conversion tracking for enhanced accuracy
- Configure conversion value rules in Microsoft Advertising for advanced attribution