Set up revenue attribution to track which marketing channels drive actual sales. Step-by-step implementation guide.
Prerequisites
Before starting:
- Zenovay tracking script installed
- Access to checkout/purchase code
- Revenue goal enabled
Basic Setup
Simple Revenue Tracking
Track revenue when a purchase completes:
// On order confirmation page or in success callback
zenovay('revenue', 99.99, 'USD');
That's it for basic tracking!
With Goal Name
Associate with a specific goal:
zenovay('goal', 'purchase', {
value: 99.99
});
Complete Implementation
Full Revenue Object
Include all relevant data:
zenovay('revenue', 149.99, 'USD', {
// Recommended
order_id: 'ORD-12345',
// Optional - for detailed analysis
items: [
{
id: 'SKU-001',
name: 'Product Name',
price: 49.99,
quantity: 2,
category: 'Electronics'
},
{
id: 'SKU-002',
name: 'Accessory',
price: 50.00,
quantity: 1,
category: 'Accessories'
}
],
// Optional metadata
coupon: 'SAVE10',
shipping: 9.99,
tax: 12.50
});
Implementation by Platform
Shopify
For Shopify stores:
- Go to Settings → Checkout
- Add to "Order status page":
{% if first_time_accessed %}
<script>
zenovay('revenue', {{ total_price | money_without_currency }}, '{{ currency }}', {
order_id: '{{ order_number }}',
items: [
{% for item in line_items %}
{
id: '{{ item.sku }}',
name: '{{ item.title | escape }}',
price: {{ item.final_price | money_without_currency }},
quantity: {{ item.quantity }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
});
</script>
{% endif %}
WooCommerce
For WordPress/WooCommerce:
- Add to your theme's
functions.phpor a plugin:
add_action('woocommerce_thankyou', 'zenovay_track_revenue');
function zenovay_track_revenue($order_id) {
$order = wc_get_order($order_id);
?>
<script>
zenovay('revenue', <?php echo $order->get_total(); ?>, '<?php echo $order->get_currency(); ?>', {
order_id: '<?php echo $order_id; ?>'
});
</script>
<?php
}
React/Next.js
In your checkout success component:
import { useEffect } from 'react';
function OrderConfirmation({ order }) {
useEffect(() => {
if (order && window.zenovay) {
window.zenovay('revenue', order.total, order.currency, {
order_id: order.id,
items: order.items.map(item => ({
id: item.sku,
name: item.name,
price: item.price,
quantity: item.quantity
}))
});
}
}, [order]);
return <div>Thank you for your order!</div>;
}
Server-Side Tracking
Enterprise PlanFor secure server-side tracking, use the tracking endpoint with your tracking code:
// Node.js example - use the tracking endpoint directly
app.post('/api/order/complete', async (req, res) => {
const order = await processOrder(req.body);
await fetch('https://api.zenovay.com/e/YOUR_TRACKING_CODE', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Forwarded-For': req.headers['x-forwarded-for'] || req.socket.remoteAddress,
},
body: JSON.stringify({
type: 'revenue',
url: req.headers.referer || 'https://yoursite.com/checkout',
revenue: order.total,
order_id: order.id,
currency: 'USD'
}),
});
res.json({ success: true });
});
Attribution Configuration
Attribution Window
Set how long to attribute:
- Go to your domain settings → Revenue tab
- Choose window length
- Save
| Window | Use Case |
|---|---|
| 7 days | Quick purchases |
| 14 days | Standard e-commerce |
| 30 days | Considered purchases |
| 60 days | B2B/high-value |
Attribution Model
Choose how credit is assigned:
- Go to your domain settings → Revenue tab
- Select default model
- Apply to reports
Models available:
- Last Touch (default)
- First Touch
- Linear
- Time Decay
- Position-Based
Cross-Device Attribution
Enterprise PlanTrack across devices:
- Identify users when they log in
- Journey stitched automatically
- Full path visible
// When user logs in
zenovay('identify', userId);
UTM Parameter Setup
Campaign Tracking
Ensure UTM parameters are used:
https://yoursite.com/?utm_source=google
&utm_medium=cpc
&utm_campaign=spring_sale
&utm_content=banner_1
UTM Parameters
| Parameter | Purpose | Example |
|---|---|---|
| utm_source | Traffic source | google, facebook |
| utm_medium | Marketing medium | cpc, email |
| utm_campaign | Campaign name | spring_sale |
| utm_content | Ad variant | banner_a |
| utm_term | Keywords | blue shoes |
Testing Setup
Debug Mode
Enable debug logging:
zenovay('debug');
Then track a test purchase and check console.
Test Purchase
- Place test order
- Check browser console
- Verify in real-time view
- Confirm in revenue report
Verification Checklist
- Revenue value correct
- Order ID recorded
- Items tracked (if sent)
- Source attributed correctly
- Currency correct
Handling Edge Cases
Recurring Revenue
For subscriptions:
// Track initial purchase
zenovay('revenue', 29.99, 'USD', {
order_id: 'SUB-001',
type: 'subscription',
interval: 'monthly'
});
// Track renewals
zenovay('revenue', 29.99, 'USD', {
order_id: 'SUB-001-RENEWAL',
type: 'subscription_renewal',
original_order: 'SUB-001'
});
Refunds
Handle refunds properly:
// Track refund
zenovay('revenue', -49.99, 'USD', {
order_id: 'REFUND-ORD-12345',
type: 'refund',
original_order: 'ORD-12345'
});
Partial Shipments
If revenue is recognized at shipping:
// Track each shipment
zenovay('revenue', 50.00, 'USD', {
order_id: 'ORD-12345-SHIP-1',
parent_order: 'ORD-12345'
});
Data Quality
Prevent Duplicates
Ensure revenue isn't tracked twice:
// Using localStorage to prevent duplicates
function trackOrderOnce(order) {
const tracked = localStorage.getItem(`tracked_${order.id}`);
if (tracked) return;
zenovay('revenue', order.total, 'USD', {
order_id: order.id
});
localStorage.setItem(`tracked_${order.id}`, 'true');
}
Validate Before Sending
Check data quality:
function trackRevenue(orderData) {
// Validate
if (!orderData.value || orderData.value <= 0) {
console.warn('Invalid order value');
return;
}
if (!orderData.order_id) {
console.warn('Missing order ID');
return;
}
// Track
zenovay('revenue', orderData.value, orderData.currency || 'USD', {
order_id: orderData.order_id
});
}
Troubleshooting
Revenue Not Appearing
If revenue doesn't show:
-
Check tracking fires
- Debug mode enabled?
- Console errors?
-
Verify goal setup
- Revenue goal created?
- Goal active?
-
Check timing
- After page fully loads?
- In correct callback?
-
Validate data
- Value is number?
- Not $0?
Attribution Missing
If source not credited:
- Check UTM parameters present
- Verify referrer not blocked
- Check attribution window
- Review cookie settings
Amounts Don't Match
If totals differ from accounting:
- Compare date ranges
- Check for refunds
- Verify currency handling
- Look for missing orders
Security Considerations
Client-Side Limitations
Be aware:
- Values can be manipulated
- Not for billing purposes
- For analytics only
Server-Side for Accuracy
For critical accuracy:
- Implement server-side tracking
- Verify against backend
- Use for reporting