Introduction
Purchase events are the most important conversion events for e-commerce tracking. This guide covers everything you need to know about tracking purchase events correctly with ServerTrack, including required parameters, user data, and best practices.
Critical: Purchase events require accurate user data (email, phone) for optimal event match quality and attribution. Always include user data when available.
When to Fire Purchase Events
Purchase events should be fired when:
- A customer successfully completes a purchase
- Payment is confirmed (not just order placed)
- The order confirmation/thank you page loads
- All order details are available (transaction ID, products, amounts)
Do NOT fire Purchase events:
- When cart is created
- When checkout is initiated
- Before payment is confirmed
- On order placement without payment confirmation
Required Parameters
Purchase events require these essential parameters:
transaction_id
Purpose: Unique identifier for the transaction (used for deduplication)
Format: String (alphanumeric)
Example: "ORD-12345" or "20240101-ABC123"
Important: transaction_id must be unique per order. Reusing the same transaction_id will cause issues with deduplication and may result in events being rejected.
value
Purpose: Total transaction value (including taxes, shipping, discounts)
Format: Number (decimal)
Example: 99.99 (for $99.99)
currency
Purpose: Currency code (ISO 4217 format)
Format: String (3-letter code)
Examples: "USD", "EUR", "BDT", "GBP"
Important Optional Parameters
contents (Product Array)
Purpose: Array of products in the order
Format: Array of objects
contents: [
{
id: "12345", // Product ID (string)
quantity: 2, // Quantity purchased (number)
item_price: 29.99 // Price per item (number)
},
{
id: "67890",
quantity: 1,
item_price: 49.99
}
]
content_ids
Purpose: Array of product IDs (used for product catalog matching)
Format: Array of strings
Example: ["12345", "67890"]
shipping
Purpose: Shipping cost
Format: Number
Example: 5.99
tax
Purpose: Tax amount
Format: Number
Example: 8.50
User Data (Critical for Purchase Events)
Purchase events should always include user data for optimal event match quality and attribution:
var userData = {
em: "customer@example.com", // Email (will be hashed automatically)
ph: "+1234567890", // Phone number (will be hashed)
fn: "John", // First name (hashed)
ln: "Doe", // Last name (hashed)
ct: "New York", // City (hashed)
st: "NY", // State (hashed)
zp: "10001", // ZIP code (hashed)
country: "us" // Country code (lowercase, hashed)
};
Note: ServerTrack automatically hashes email, phone, and other PII data using SHA256 before sending to platforms. You send the raw data, and we handle the hashing.
Complete Purchase Event Example
// User data (collected from checkout form)
var userData = {
em: "john.doe@example.com",
ph: "+1234567890",
fn: "John",
ln: "Doe",
ct: "New York",
st: "NY",
zp: "10001",
country: "us"
};
// Purchase event
st('track', 'Purchase', {
currency: "USD",
value: 104.98, // Total: $99.99 (products) + $4.99 (shipping)
transaction_id: "ORD-20240101-12345",
shipping: 4.99,
tax: 0, // If applicable
content_type: 'product',
content_ids: ["12345", "67890"], // Product IDs
contents: [
{
id: "12345",
quantity: 2,
item_price: 29.99
},
{
id: "67890",
quantity: 1,
item_price: 49.99
}
]
}, userData);
Platform-Specific Notes
Facebook Conversions API
- transaction_id is required and used for deduplication
- User data (especially email/phone) significantly improves Event Match Quality
- contents array helps with product catalog matching
- value should include all charges (products, shipping, tax)
TikTok ePIG
- Event is automatically mapped to "CompletePayment"
- Similar requirements to Facebook CAPI
- User data improves algorithm optimization
Google Analytics 4
- Event is mapped to "purchase"
- transaction_id, value, and currency are required
- Items array (contents) should include item_id, price, and quantity
Implementation Examples
Shopify Implementation
{% if first_time_accessed %}
<script>
var userData = {
em: "{{ checkout.email }}",
ph: "{{ checkout.shipping_address.phone }}",
fn: "{{ checkout.shipping_address.first_name }}",
ln: "{{ checkout.shipping_address.last_name }}",
ct: "{{ checkout.shipping_address.city }}",
country: "{{ checkout.shipping_address.country_code | downcase }}"
};
var contents = [];
{% for line_item in checkout.line_items %}
contents.push({
id: "{{ line_item.product_id }}",
quantity: {{ line_item.quantity }},
item_price: {{ line_item.price | divided_by: 100.0 }}
});
{% endfor %}
st('track', 'Purchase', {
currency: "{{ checkout.currency }}",
value: {{ checkout.total_price | divided_by: 100.0 }},
transaction_id: "{{ checkout.order_id }}",
shipping: {{ checkout.shipping_price | divided_by: 100.0 }},
content_ids: [{% for line_item in checkout.line_items %}"{{ line_item.product_id }}"{% unless forloop.last %},{% endunless %}{% endfor %}],
contents: contents
}, userData);
</script>
{% endif %}
WooCommerce Implementation
add_action('woocommerce_thankyou', 'track_purchase_event', 10, 1);
function track_purchase_event($order_id) {
$order = wc_get_order($order_id);
if (!$order) return;
$userData = array(
'em' => $order->get_billing_email(),
'ph' => $order->get_billing_phone(),
'fn' => $order->get_billing_first_name(),
'ln' => $order->get_billing_last_name(),
'ct' => $order->get_billing_city(),
'country' => strtolower($order->get_billing_country())
);
$contents = array();
foreach ($order->get_items() as $item) {
$contents[] = array(
'id' => (string)$item->get_product_id(),
'quantity' => $item->get_quantity(),
'item_price' => $item->get_subtotal() / $item->get_quantity()
);
}
$eventData = array(
'currency' => $order->get_currency(),
'value' => $order->get_total(),
'transaction_id' => (string)$order_id,
'shipping' => $order->get_shipping_total(),
'content_ids' => array_map(function($item) {
return (string)$item->get_product_id();
}, $order->get_items()),
'contents' => $contents
);
echo "<script>st('track', 'Purchase', " . json_encode($eventData) . ", " . json_encode($userData) . ");</script>";
}
Best Practices
- Always include user data: Email and phone significantly improve event match quality
- Use unique transaction IDs: Never reuse transaction IDs
- Include all charges: value should equal sum of products + shipping + tax
- Fire on confirmation page: Only fire after payment is confirmed
- Include product details: contents array helps with product catalog and optimization
- Test thoroughly: Use test purchases to verify events before going live
Testing Purchase Events
- Complete a test purchase on your store
- Check ServerTrack dashboard → Event Logs
- Look for Purchase event with status "success" or "pending"
- Verify all parameters are present and correct
- Check Facebook Events Manager Test Events (should appear within seconds)
- Verify transaction_id is unique and not duplicated
Troubleshooting
Purchase Events Not Appearing
- Verify script is loaded before purchase event code
- Check that event is firing on the correct page (order confirmation)
- Ensure Server Deck status is "Active"
- Review event logs for error messages
Duplicate Purchase Events
- Ensure transaction_id is unique for each order
- Fire event only once per order (use flags to prevent duplicate fires)
- Check if both browser pixel and server-side are firing (should use same event_id for deduplication)
Summary
Purchase events are critical for conversion tracking. Always include:
- Required: transaction_id, value, currency
- Recommended: user data (email, phone), contents array, shipping, tax
- Fire only after payment confirmation
- Use unique transaction IDs
- Test thoroughly before going live
For more information, see our Standard Events Reference Guide and User Data Collection and Privacy guide.