Setting Up Conversion Attribution for Sites
Attribution is distributing credit for conversion among ad channels. User sees banner, then finds via search, 3 days later returns via email and buys. Which channel gets credit? Answer depends on attribution model.
Attribution Models
| Model | Logic | When to Use |
|---|---|---|
| Last Click | 100% to last channel before purchase | Quick decisions, low ticket |
| First Click | 100% to first touchpoint | Assessing new customer acquisition channels |
| Linear | Equal split among all channels | Long sales cycle |
| Time Decay | More weight to recent touchpoints | Short deal cycle |
| Position-based | 40% first + 40% last + 20% others | Balance acquisition and conversion |
| Data-driven | ML based on real GA4 data | Sufficient data (1000+ conversions/month) |
Configuration in GA4
GA4 uses Data-Driven Attribution by default. Switch:
GA4 → Admin → Attribution Settings → Reporting Attribution Model
To compare models:
Reports → Advertising → Attribution → Model Comparison
Select two channels (e.g., Paid Search and Email) and compare their contribution across models.
Storing UTM Parameters in DB
For custom attribution — store UTM parameters on each visit:
// On page load
const utmParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
const currentUtm = {};
const urlParams = new URLSearchParams(window.location.search);
utmParams.forEach(param => {
if (urlParams.has(param)) {
currentUtm[param] = urlParams.get(param);
sessionStorage.setItem(param, urlParams.get(param));
}
});
// Save to localStorage for last-touch
if (Object.keys(currentUtm).length > 0) {
localStorage.setItem('last_utm', JSON.stringify({ ...currentUtm, timestamp: Date.now() }));
}
// On checkout — pass UTM parameters
$order->update([
'utm_source' => session('utm_source'),
'utm_medium' => session('utm_medium'),
'utm_campaign' => session('utm_campaign')
]);
Multi-channel Attribution on Server
-- Analyze conversions by first-touch attribution
SELECT
first_visit.utm_source,
COUNT(DISTINCT o.id) as orders,
SUM(o.total) / 100.0 as revenue
FROM orders o
JOIN sessions first_visit ON first_visit.user_id = o.user_id
AND first_visit.id = (
SELECT id FROM sessions
WHERE user_id = o.user_id
ORDER BY created_at ASC
LIMIT 1
)
WHERE o.created_at >= NOW() - INTERVAL '30 days'
GROUP BY first_visit.utm_source
ORDER BY revenue DESC;
Attribution Window
Window is how many days back a touchpoint must be to count. GA4 default: 30 days for conversions, 90 days for purchases. For B2B with long cycle — increase to 90–180 days.
Setup time: 2–3 days for GA4 setup + UTM storage in DB.







