Attribution Multi-Touch di SQL: Membagi Kredit Konversi Antar Kanal
TL;DR
Attribution multi-touch adalah cara bagi kredit satu konversi ke semua kanal yang disentuh pelanggan sebelum beli, bukan cuma ke kanal terakhir. Di SQL, semua model dibangun dari satu kerangka yang sama: gabungin touchpoint ke konversi dalam jendela waktu tertentu, urutkan pakai ROW_NUMBER, hitung jumlah touchpoint per konversi, lalu kalikan pendapatan dengan bobot sesuai model. Lima model yang paling sering dipakai adalah first touch, last touch, linear, position based 40-20-40, dan time decay.
Attribution multi-touch adalah cara bagi kredit satu pembelian ke semua kanal yang disentuh pelanggan sebelum dia beli, bukan cuma ke kanal terakhir.
Contoh yang sering kejadian: pelanggan lihat iklan Instagram hari Senin, klik email promo hari Rabu, terus beli hari Sabtu setelah nyari nama tokomu di Google.
Kalau kamu pakai laporan bawaan yang cuma ngitung sentuhan terakhir, semua kredit jatuh ke pencarian. Iklan Instagram yang bikin dia kenal tokomu tercatat nol.
Di bawah ini lima model attribution beserta query SQL-nya, plus contoh angka dari toko online yang datanya aku olah sendiri.
Kenapa attribution single touch bikin keputusan anggaran salah?
Karena model sentuhan terakhir ngasih 100% kredit ke kanal yang kebetulan ada di ujung. Kanal itu biasanya pencarian merek atau ketik langsung, dua hal yang paling gampang kalau orangnya udah kenal tokomu. Kanal yang tugasnya ngenalin merek jadi keliatan nggak menghasilkan apa-apa, lalu anggarannya dipotong.
Efek lanjutannya baru kerasa dua bulan setelah anggaran dipotong, waktu jumlah pencarian merek ikut turun.
Model multi-touch nggak bikin angkanya jadi benar secara mutlak. Dia bikin perbandingan antar kanal lebih adil, dan itu udah cukup buat nentuin prioritas anggaran.
Data apa yang dibutuhin buat attribution multi-touch?
Dua tabel aja cukup.
Tabel touchpoint nyimpen tiap interaksi: siapa, dari kanal mana, kapan.
user_id | channel | touched_at
--------+------------------+---------------------
U1021 | instagram_ads | 2025-09-01 19:22:00
U1021 | email | 2025-09-03 08:10:00
U1021 | google_organic | 2025-09-06 20:41:00
Tabel konversi nyimpen pembeliannya: siapa, order berapa, kapan, nilainya berapa.
user_id | order_id | converted_at | revenue
--------+----------+---------------------+---------
U1021 | ORD-9912 | 2025-09-06 20:55:00 | 485000
Kalau kamu belum punya kolom user_id yang konsisten di kedua tabel, beresin itu dulu. Tanpa itu, sentuhan dari HP dan dari laptop bakal kebaca sebagai dua orang berbeda.
Gimana kerangka query yang dipakai semua model?
Semua model attribution dibangun dari satu CTE yang sama. Tiga langkahnya begini.
- Gabungin touchpoint ke konversi, dibatasi jendela waktu tertentu (lookback window).
- Urutkan sentuhan per konversi pakai
ROW_NUMBER. - Hitung total sentuhan per konversi pakai
COUNTsebagai window function.
WITH perjalanan AS (
SELECT
k.order_id,
k.revenue,
k.converted_at,
t.channel,
t.touched_at,
ROW_NUMBER() OVER (PARTITION BY k.order_id ORDER BY t.touched_at) AS urutan,
COUNT(*) OVER (PARTITION BY k.order_id) AS total_touch
FROM konversi k
JOIN touchpoint t
ON t.user_id = k.user_id
AND t.touched_at <= k.converted_at
AND t.touched_at >= k.converted_at - INTERVAL '30 days'
)
SELECT * FROM perjalanan ORDER BY order_id, urutan;
Hasilnya satu baris per pasangan sentuhan dan pembelian, lengkap dengan nomor urut dan total sentuhannya.
Angka 30 hari di situ jendela lookback. Ganti sesuai berapa lama pelanggan kamu biasanya mikir sebelum beli. Sintaks lengkap window function ada di dokumentasi PostgreSQL.
Gimana query untuk tiap model attribution?
1. First touch
Seratus persen kredit ke sentuhan pertama. Cocok buat ngukur kanal mana yang paling jago ngenalin merek ke orang baru.
SELECT channel, SUM(revenue) AS kredit
FROM perjalanan
WHERE urutan = 1
GROUP BY channel
ORDER BY kredit DESC;
2. Last touch
Seratus persen kredit ke sentuhan terakhir. Ini default hampir semua tool iklan.
SELECT channel, SUM(revenue) AS kredit
FROM perjalanan
WHERE urutan = total_touch
GROUP BY channel
ORDER BY kredit DESC;
3. Linear
Kredit dibagi rata ke semua sentuhan. Paling gampang dijelasin ke orang non teknis.
SELECT channel, SUM(revenue::numeric / total_touch) AS kredit
FROM perjalanan
GROUP BY channel
ORDER BY kredit DESC;
Perhatiin ::numeric di situ. Tanpa itu, pembagian antar bilangan bulat bakal dipotong dan totalnya nggak bakal cocok.
4. Position based (40-20-40)
Sentuhan pertama dapat 40%, sentuhan terakhir dapat 40%, sisanya 20% dibagi rata ke sentuhan tengah. Ini kompromi yang paling sering dipakai tim marketing.
SELECT
channel,
SUM(
CASE
WHEN total_touch = 1 THEN revenue
WHEN total_touch = 2 THEN revenue * 0.5
WHEN urutan IN (1, total_touch) THEN revenue * 0.4
ELSE revenue * 0.2 / (total_touch - 2)
END
) AS kredit
FROM perjalanan
GROUP BY channel
ORDER BY kredit DESC;
Dua kasus khusus di atas penting. Kalau cuma ada satu sentuhan, dia dapat semuanya. Kalau ada dua, masing-masing dapat setengah. Tanpa dua baris CASE itu, query kamu bakal bagi dengan nol.
5. Time decay
Sentuhan yang lebih dekat ke waktu pembelian dapat bobot lebih besar. Bobotnya turun setengah tiap 7 hari.
WITH bobot AS (
SELECT
order_id,
channel,
revenue,
POWER(
0.5,
EXTRACT(EPOCH FROM (converted_at - touched_at)) / (7 * 86400)
) AS w
FROM perjalanan
)
SELECT
channel,
SUM(revenue * w / SUM(w) OVER (PARTITION BY order_id)) AS kredit
FROM bobot
GROUP BY channel
ORDER BY kredit DESC;
Angka 7 di penyebut itu waktu paruh. Kecilin jadi 3 kalau produk kamu dibeli cepat setelah orang lihat iklan.
Contoh kasus: toko online perlengkapan bayi
Aku olah data dummy dari pola toko online perlengkapan bayi selama satu kuartal. Total 3.140 pembelian, nilai Rp 1,86 miliar, empat kanal utama, jendela lookback 30 hari.
Rata-rata jumlah sentuhan sebelum beli: 3,2. Cuma 18% pembelian yang cuma punya satu sentuhan.
| Kanal | Last touch | First touch | Linear | Selisih last vs linear |
|---|---|---|---|---|
| google_organic | Rp 712 juta | Rp 268 juta | Rp 468 juta | -34% |
| instagram_ads | Rp 394 juta | Rp 731 juta | Rp 549 juta | +39% |
| Rp 502 juta | Rp 291 juta | Rp 447 juta | -11% | |
| tiktok_ads | Rp 252 juta | Rp 570 juta | Rp 396 juta | +57% |
Yang paling mencolok, tiktok_ads naik 57% kreditnya begitu pindah dari last touch ke linear. Kanal itu muncul sebagai sentuhan pertama di 41% perjalanan pembelian, tapi cuma jadi sentuhan terakhir di 8%.
Kalau anggaran tiktok_ads dipotong berdasarkan laporan last touch, yang ikut turun dua bulan kemudian bukan cuma TikTok. Pencarian merek di Google juga ikut turun, karena pasokan orang yang baru kenal tokomu berkurang.
Angka ini juga nunjukin satu hal: pilihan model bisa ngubah kredit satu kanal sampai lebih dari setengah, tanpa satu pun iklan berubah.
Kesalahan apa yang paling sering bikin hasil attribution ngawur?
Total kredit nggak sama dengan total pendapatan. Cek ini duluan tiap kali. Kalau SUM(kredit) beda dari SUM(revenue) di tabel konversi, biasanya ada order yang nggak punya touchpoint sama sekali dalam jendela lookback dan kebuang gara-gara INNER JOIN. Ganti ke LEFT JOIN, lalu masukin sisanya ke kategori langsung.
Pembagian bilangan bulat. Di PostgreSQL, revenue / total_touch antar integer bakal dipotong desimalnya. Selisihnya kecil per baris, tapi numpuk di ribuan order. Selalu cast ke numeric.
Sentuhan duplikat dari halaman yang di-refresh. Satu orang buka halaman tiga kali dalam semenit bakal kecatat tiga touchpoint dan bikin bobotnya melar. Ringkas dulu jadi satu sentuhan per kanal per sesi sebelum masuk ke query attribution.
Jendela lookback asal pilih. Jangan pakai 30 hari cuma karena semua orang pakai itu. Hitung selisih waktu antara sentuhan pertama dan pembelian, ambil persentil 90-nya, lalu bulatkan.
Nganggap hasilnya sebab akibat. Attribution itu aturan pembagian, bukan bukti bahwa kanal itu yang bikin orang beli. Kalau kamu butuh jawaban sebab akibat, jalanin A/B testing dengan grup kontrol.
Model mana yang sebaiknya kamu pakai?
| Model | Paling pas buat | Kelemahannya |
|---|---|---|
| First touch | Ngukur kanal pencari pelanggan baru | Ngabaikan semua yang bikin orang akhirnya beli |
| Last touch | Perbandingan cepat, laporan standar | Menggemukkan kanal merek dan pencarian |
| Linear | Laporan bulanan yang gampang dijelasin | Nganggap semua sentuhan sama beratnya |
| Position based | Perusahaan yang punya kanal awal dan akhir jelas | Angka 40-20-40 dipilih, bukan diukur |
| Time decay | Siklus beli pendek, promo musiman | Ngerendahin kanal pengenalan merek |
Saran praktisnya: jalanin dua model sekaligus di laporan yang sama. Last touch buat bandingin sama laporan platform iklan, linear atau position based buat nentuin anggaran. Selisih antar keduanya justru bagian yang paling menarik dilihat.
Sebelum ini semua, pastiin dulu metric konversi kamu didefinisikan seragam antar tim. Attribution di atas definisi yang berantakan cuma bikin salah paham makin rapi kelihatannya.
FAQ
Attribution multi-touch itu apa sih?
Attribution multi-touch adalah cara bagi kredit satu pembelian ke semua kanal yang disentuh pelanggan sebelum dia beli. Kalau seseorang lihat iklan Instagram, klik email promo, lalu beli lewat pencarian Google, model multi-touch ngasih porsi kredit ke ketiganya. Bandingannya model single touch yang cuma ngasih 100% ke satu kanal, biasanya yang terakhir. Multi-touch bikin kanal awal yang tugasnya ngenalin merek nggak keliatan nol terus.
Model attribution mana yang paling akurat?
Nggak ada yang akurat dalam arti benar secara ilmiah. Semua model itu aturan pembagian yang kamu pilih, bukan pengukuran sebab akibat. Kalau kamu beneran mau tau kanal mana yang bikin orang beli, jalanin eksperimen dengan grup kontrol. Model attribution berguna buat ngebandingin kanal secara konsisten dari waktu ke waktu, bukan buat ngeklaim satu kanal penyebab pastinya.
Berapa lama jendela lookback yang wajar?
Tergantung berapa lama orang mikir sebelum beli. Buat barang murah yang dibeli impulsif, 7 sampai 14 hari biasanya cukup. Buat barang mahal kayak elektronik atau layanan langganan tahunan, 30 sampai 90 hari lebih masuk akal. Cara ngeceknya gampang: hitung selisih waktu antara sentuhan pertama dan pembelian, lalu ambil persentil 90 dari distribusinya. Itu titik awal yang wajar.
Kenapa total pendapatan hasil attribution-ku nggak sama dengan total penjualan?
Biasanya karena ada konversi yang nggak punya touchpoint sama sekali di dalam jendela lookback. Pembelian itu hilang dari hasil kalau kamu pakai INNER JOIN. Solusinya, pakai LEFT JOIN lalu masukin sisanya ke kategori langsung atau tidak diketahui. Penyebab kedua, pembulatan pada model linear. Selalu cek total kredit hasil query kamu sama dengan total pendapatan asli sebelum dibagikan ke orang lain.
Bisa nggak bikin attribution multi-touch tanpa data user ID?
Susah. Kamu butuh cara nyambungin banyak sentuhan ke satu orang yang sama. Kalau nggak ada user ID, alternatifnya pakai ID perangkat atau cookie, tapi hasilnya bakal pecah begitu orang ganti HP ke laptop. Buat toko online, cara paling praktis adalah nyimpen ID pelanggan begitu mereka login atau checkout, lalu nyambungin sesi anonim sebelumnya ke ID itu.
Penutup
Tiga hal yang paling penting dari semua di atas.
Satu, semua model attribution numpang di kerangka SQL yang sama. Begitu CTE perjalanan jadi, nambah model cuma soal ganti rumus bobotnya.
Dua, selisih antar model itu informasi, bukan gangguan. Kanal yang kreditnya lompat jauh antar model biasanya kanal pengenalan merek yang selama ini kamu remehkan.
Tiga, cek total kredit sama dengan total pendapatan sebelum laporannya dikirim.
Mau latihan query yang mirip? Coba analisis funnel yang bocor lewat SQL. Buat kamu yang baru masuk tim data dan lagi nyusun prioritas, ada juga rencana 90 hari pertama sebagai analis data.
Coba jalanin dua model di data kamu minggu ini, lalu lihat kanal mana yang paling banyak berubah.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel terkait
Cara Membuat Pivot Dinamis di SQL (Panduan 2026)
Pivot dinamis di SQL ngubah baris jadi kolom tanpa kamu hardcode nama kolomnya. Ini cara bikinnya pakai CASE WHEN dan versi yang kolomnya ngikut data.
Menghitung YTD, QTD, dan MTD di SQL (Panduan 2026)
YTD, QTD, dan MTD ngukur total dari awal tahun, kuartal, atau bulan sampai hari ini. Ini cara ngitungnya di SQL pakai DATE_TRUNC, plus satu query gabungan.
Gap and Island Analysis di SQL
Gap and island analysis di SQL nyari deret data yang berturut-turut (island) dan celah yang bolong (gap). Cocok buat hitung streak login atau cari tanggal transaksi yang hilang.