Identitas Halaman
- Nama file,
page-detail-followup-lead.php
- URL,
https://web.putuadi.id/marketing/detail-lead/detail-followup-lead/?idl=LD2602151537481362
- Modul, CRM, Marketing
- Fungsi utama, menampilkan dan mengelola roadmap follow up (jadwal konten follow up) untuk 1 lead, berdasarkan template yang sudah dibuat di master Followup Templates dan Followup Template Groups.
- Prompt : https://chatgpt.com/share/6995fe9a-d5e4-8006-87dd-548202c2fb23
1) Konsep Besar, Apa yang Dikerjakan Halaman Ini
Halaman ini adalah “monitoring dan eksekusi” roadmap follow up untuk satu lead.
Yang terjadi di halaman ini secara sederhana:
- Sistem membaca data lead dari
tb_leads.
- Sistem membaca daftar item roadmap dari
tb_lead_roadmap_items, dan join ke tb_followup_templates untuk mengambil judul konten dan teks template follow up.
- Sistem menampilkan item-item roadmap, dikelompokkan per stage Customer Journey (Awareness, Consideration, Purchase, Retention, Advocacy).
- User bisa melakukan aksi:
- Generate roadmap awal dari sebuah Followup Template Group (khusus lead yang belum punya item roadmap sama sekali).
- Generate stage berikutnya (Retention atau Advocacy) jika stage sebelumnya sudah selesai.
- Menandai item sebagai terkirim atau skip.
- Membuka modal “Lihat teks” untuk melihat isi pesan follow up, lalu copy.
- Klik tombol WhatsApp untuk mengirim pesan yang sudah dirender (template diisi variabel lead) via
wa.me.
Output akhirnya, lead punya jadwal follow up yang rapi, bisa dieksekusi manual oleh tim, dan status tiap follow up bisa dipantau.
2) Parameter URL
Parameter wajib
idl, ID lead
- Contoh,
?idl=LD2602151537481362
- Disanitasi, hanya alfanumerik (
A-Za-z0-9), karakter lain dibuang.
Jika idl kosong atau tidak valid, halaman menampilkan pesan warning.
Parameter opsional
debug=1
- Menampilkan panel debug berisi SQL loader items dan total rows yang didapat.
- Tujuan, melacak masalah data kosong, join tidak match, filter salah, dan sebagainya.
3) Dependensi File Include
Halaman ini mengandalkan beberapa include internal:
include_crm_helpers.php
- Helper umum, misalnya:
wb_get_current_user_login_safe()
wb_wa_digits() untuk normalisasi nomor WhatsApp
wb_tpl_render() untuk render template text dengan variabel lead
wb_format_datetime_id() untuk format datetime tampilan
include_crm_db.php
- Menyediakan koneksi DB, variabel
mysqli $koneksi
- Bisa juga menyediakan
$dbError jika koneksi bermasalah
include_crm_definitions.php
- Definisi stage, label, dan mapping yang dipakai UI dan normalisasi
- Umumnya menyediakan array
$stages seperti:
- awareness, consideration, purchase, retention, advocacy
- masing-masing punya
label
include_crm_roadmap.php
- Helper roadmap tambahan
- Yang dipakai di halaman ini:
wb_roadmap_mark_item(...) untuk update status item
- Layout:
header.php, sidebar.php, topbar.php, footer.php
include_tentang_halaman.php
4) Tabel Database yang Dipakai
Halaman ini memakai 4 tabel utama (dan 1 tabel opsional).
A. tb_leads
Dipakai untuk:
- Ambil data lead yang sedang dibuka
- Ambil
stage lead untuk menentukan stage mana yang tampil dan aturan generate
- Simpan
template_group pada lead saat generate roadmap awal
Kolom yang biasa dipakai (minimal):
id_lead
full_name
company_name
email
phone
lead_magnet
stage
template_group (opsional tapi dipakai bila ada)
updated_at
B. tb_lead_roadmap_items
Ini tabel inti, berisi item roadmap per lead.
Kolom minimal yang diasumsikan ada:
id_item (ID item roadmap)
id_roadmap (relasi ke roadmap header)
id_lead
id_template
stage
step_no
day_number
scheduled_at
status (pending, sent, skipped)
created_at
updated_at
C. tb_followup_templates
Master isi konten follow up.
Kolom minimal yang dipakai di halaman ini:
id_template
stage
step_no
day_number
title
message_text
channel
template_group (dipakai untuk filter berdasarkan group)
is_active (opsional, jika ada, hanya yang aktif yang diambil)
D. tb_followup_template_groups
Master group drip sequence.
Kolom yang dipakai:
id_group
group_key
group_name
default_send_time (HH:MM:SS)
timezone_name (opsional)
is_active
E. tb_lead_roadmaps (opsional)
Dipakai sebagai “header roadmap”.
Jika tabel ini ada, halaman akan:
- Cek apakah lead sudah punya roadmap header
- Jika belum ada, buat baru
id_roadmap
- Simpan metadata group bila kolom tersedia (template_group, group_key, group_name, id_group, created_by, updated_by)
Kalau tabel ini tidak ada, halaman tetap bisa jalan, karena id_roadmap bisa dibuat secara internal untuk item.
5) Struktur Data dan Relasi yang Dipakai
Konsep relasi ideal:
- 1 Lead (
tb_leads)
- punya 1 Roadmap header (
tb_lead_roadmaps) opsional
- punya banyak Roadmap items (
tb_lead_roadmap_items)
- setiap item merujuk ke 1 Template (
tb_followup_templates)
Di UI, item-item roadmap akan ditampilkan per stage.
6) Komponen UI yang Ditampilkan
6.1 Header halaman
- Pretitle, “CRM”
- Title, “Roadmap Follow up Lead”
- Subtitle, “Peta jadwal konten follow up untuk 1 lead”
- Tombol kembali, kembali ke halaman detail lead,
/marketing/detail-lead/?idl=...
6.2 Lead summary card
Menampilkan informasi lead:
- Nama lengkap
- Avatar
- jika ada URL foto di kolom tertentu, dipakai sebagai background image avatar
- kalau tidak ada, pakai inisial nama
- Company, email
- Badge:
- Stage label
- Traffic Temperature
- Lead magnet (jika ada)
Tombol:
- Detail Lead
- WhatsApp, jika nomor valid
6.3 Panel “Generate jadwal follow up” (hanya kondisi tertentu)
Panel ini hanya muncul kalau:
- lead valid, dan
- jumlah roadmap items untuk lead ini = 0, dan
- tabel group ada dan group list tersedia
Isi panel:
- dropdown Followup Template Group
- tombol Generate (submit form)
6.4 Card per stage
Halaman menampilkan beberapa stage sesuai aturan visibleStages (dibahas di bagian aturan).
Tiap card stage berisi:
- Badge nama stage
- Ringkasan progress, total, selesai, pending
- Progress bar
- Tabel daftar item roadmap stage tersebut
Tabel item roadmap kolom:
- No
- Konten (judul template, hari ke berapa)
- Jadwal (scheduled_at)
- Status (Pending, Terkirim, Skip)
- Tombol WhatsApp (langsung ke
wa.me + text)
- Dropdown aksi:
- Lihat teks (modal)
- Tandai terkirim
- Skip
6.5 Modal “Teks Follow up”
Modal menampilkan:
- Title (judul konten)
- Textarea isi pesan yang sudah dirender
- Tombol Copy
- Tombol Tutup
Ada fallback jika Bootstrap modal tidak tersedia, modal tetap bisa tampil dengan JS manual.
6.6 Toast notifikasi
Jika ada query ?flash=...&msg=..., halaman memunculkan toast.
Setelah toast muncul, URL dibersihkan (flash dan msg dihapus dari query string) supaya tidak muncul lagi saat refresh.
7) Aturan Stage, Traffic Temperature, dan Stage yang Ditampilkan
7.1 Mapping Traffic Temperature (untuk badge)
- Awareness, Cold
- Consideration, Warm
- Purchase, Retention, Advocacy, Hot
7.2 Stage yang ditampilkan (visibleStages)
Aturannya:
- Jika lead stage = awareness atau consideration
- tampilkan, awareness dan consideration
- ini untuk memastikan nurture awal tetap terlihat dua stage pertama
- Jika lead stage = purchase
- tampilkan purchase
- jika sudah ada item retention, tampilkan retention juga
- Jika lead stage = retention
- tampilkan retention
- jika sudah ada item advocacy, tampilkan advocacy juga
- Jika lead stage = advocacy
- Jika stage lead tidak dikenal
- fallback, tampil awareness dan consideration
8) Aksi dan Form POST yang Didukung
Halaman mengenali POST berdasarkan wb_action.
8.1 Mark item, terkirim atau skip
wb_action = mark_item_sent
wb_action = mark_item_skipped
Input:
Proses:
- Panggil
wb_roadmap_mark_item($koneksi, $idItem, $status, $userLogin, $note, $err)
- Redirect balik ke halaman ini dengan flash message
Status yang dipakai:
sent
skipped
- default,
pending
8.2 Generate roadmap awal dari group
wb_action = generate_from_group
Kondisi:
- Lead harus ada
- Lead belum punya item roadmap sama sekali
- Group harus valid dan aktif
Input:
group_id (id_group dari tb_followup_template_groups)
Proses besar:
- Ambil lead
- Cek ada item roadmap atau tidak, kalau sudah ada, generate diblok
- Ambil data group, termasuk default_send_time dan timezone
- Tentukan stage yang akan digenerate:
- Jika lead stage awareness atau consideration, generate dua stage, awareness dan consideration
- Jika lead stage masuk hot (purchase, retention, advocacy), generate hanya stage lead saat ini
- Jika tidak jelas, fallback awareness dan consideration
- Ambil template dari
tb_followup_templates:
- stage termasuk stage yang ditentukan
- template_group harus match salah satu kandidat group:
id_group, group_key, group_name
- jika ada kolom
is_active, hanya ambil yang is_active=1
- urutan item:
- berdasarkan stage urutan fixed
- lalu
day_number, lalu step_no, lalu id_template
- Buat roadmap header di
tb_lead_roadmaps jika tabelnya ada dan lead belum punya
- Simpan
template_group ke lead jika kolomnya ada
- Insert ke
tb_lead_roadmap_items untuk setiap template yang lolos
- mencegah dobel, jika sudah ada item untuk id_template tersebut, skip
- hitung
scheduled_at per template, berdasarkan aturan scheduling
- Redirect dengan flash success, menyebut total item yang berhasil dibuat
8.3 Generate stage berikutnya
wb_action = generate_next_stage
Input:
stage_to, hanya boleh retention atau advocacy
Aturan boleh generate:
- stage_to = retention, hanya jika lead stage sekarang = purchase, dan semua item purchase sudah selesai, dan retention belum ada item
- stage_to = advocacy, hanya jika lead stage sekarang = retention, dan semua item retention sudah selesai, dan advocacy belum ada item
Proses:
- Validasi stage_to
- Ambil lead, normalisasi stage
- Validasi aturan di atas
- Ambil
id_roadmap yang sudah ada:
- prioritas dari
tb_lead_roadmap_items
- fallback ke
tb_lead_roadmaps jika ada
- Ambil template stage_to
- jika lead punya
template_group dan group bisa diresolve, filter template_group sesuai kandidat group
- jika ada
is_active, ambil yang aktif
- Insert item roadmap seperti proses awal, hitung scheduled_at mulai dari hari ini
- Update
tb_leads.stage menjadi stage_to
- Redirect dengan flash message
9) Algoritma Perhitungan Jadwal scheduled_at
Fungsi:
wb_calc_scheduled_at($baseDate, $baseTime, $dayNum, $stepNo, $tzObj)
Aturan penting yang diterapkan:
- Tanggal mulai selalu hari ini
$baseDate = date('Y-m-d')
- Day number dipetakan ke offset hari seperti ini:
day_number = 0, offset hari 0, tetap hari ini
day_number = 1, offset hari 0, tetap hari ini
day_number = 2, offset hari 1, besok
day_number = 3, offset hari 2, lusa
- rumus, jika
day_number >= 2, offsetDays = day_number – 1
- Time default
- Diambil dari
tb_followup_template_groups.default_send_time
- Jika tidak valid, fallback
09:00:00
- Offset menit berdasarkan step number
step_no dipakai untuk menggeser menit, supaya dalam 1 hari tidak semua pesan punya jam yang sama
- rumus,
(step_no - 1) * 10 menit
- contoh:
- step 1, +0 menit
- step 2, +10 menit
- step 3, +20 menit
- Timezone
- Jika group memiliki
timezone_name, dipakai untuk membentuk DateTime
- Jika invalid, sistem fallback ke timezone default server PHP
Contoh konkret:
- baseDate hari ini, 2026-02-19
- baseTime, 09:00:00
Template A, day_number 1, step_no 1
- offset hari 0, jam 09:00
- scheduled_at = 2026-02-19 09:00:00
Template B, day_number 1, step_no 3
- offset hari 0, jam 09:20
- scheduled_at = 2026-02-19 09:20:00
Template C, day_number 2, step_no 1
- offset hari 1, jam 09:00
- scheduled_at = 2026-02-20 09:00:00
10) Render Template Pesan dan Variabel yang Dipakai
Template pesan berasal dari tb_followup_templates.message_text.
Sebelum dikirim ke WhatsApp atau ditampilkan di modal, pesan dirender dengan variabel lead:
Variabel yang disiapkan di halaman:
$varsLead = [
'full_name' => $leadName,
'company_name' => $leadComp,
'email' => $leadEmail,
'phone' => $leadPhone,
'lead_magnet' => $leadMagnet,
'freebie_link' => '',
];
Render dilakukan oleh helper:
wb_tpl_render($message_text, $varsLead)
Catatan:
- Kalau masih ada token seperti
{{freebie_link}}, artinya datanya belum diisi, karena di halaman ini freebie_link masih string kosong.
- Ini sengaja, karena ada konteks bahwa beberapa data bisa diisi belakangan, atau punya sumber lain.
11) Integrasi WhatsApp (Manual Execution)
Di setiap item, tombol WhatsApp membuat URL seperti:
https://wa.me/<digits>?text=<encoded_message>
Nomor WhatsApp:
- Diproses oleh helper
wb_wa_digits($leadPhone)
- Jika tidak bisa dinormalisasi menjadi digits valid, tombol WhatsApp tidak muncul (diganti tanda “-”).
Pesan:
- Pesan sudah dalam kondisi final (template sudah dirender)
- Ditambahkan ke query
text=... melalui rawurlencode
Tujuannya:
- Tim bisa follow up manual satu per satu, tetapi tetap konsisten dari sisi pesan dan urutan jadwal.
12) Status Item dan Progress Stage
12.1 Status yang digunakan
pending, default saat item dibuat
sent, saat follow up sudah dikirim
skipped, saat item dilewati
Badge status:
- pending, warning
- sent, success
- skipped, secondary
12.2 Perhitungan progress per stage
Fungsi:
wb_stage_progress($items) menghasilkan:
- total
- done, sent + skipped
- pending
Progress bar:
12.3 Definisi “stage selesai”
Fungsi:
wb_stage_completed($items)
- stage dianggap selesai jika semua item statusnya sent atau skipped
Aturan ini dipakai untuk mengaktifkan tombol:
- Generate Stage Retention
- Generate Stage Advocacy
13) Proteksi, Validasi, dan Pencegahan Duplikasi
Halaman ini punya beberapa proteksi penting:
- Validasi lead harus ada
- Validasi tabel wajib harus ada
- Generate roadmap awal diblok jika lead sudah punya item roadmap
- Insert item dicek satu per satu, tidak boleh ada item ganda:
- cek
SELECT 1 FROM tb_lead_roadmap_items WHERE id_lead=? AND id_template=? LIMIT 1
- Generate stage berikutnya diblok jika:
- stage sekarang tidak sesuai aturan
- stage sebelumnya belum selesai
- stage target sudah punya item
14) Error Handling dan Debugging
14.1 Gaya error di halaman
- Error kritis koneksi atau struktur tabel disimpan ke
$dbError, lalu ditampilkan sebagai alert warning.
- Error operasi generate dan insert biasanya diarahkan ke redirect + flash message, sehingga user tetap di halaman yang sama, tidak “white screen”.
14.2 Debug mode sederhana
- Tambahkan
&debug=1
- Halaman menampilkan:
- SQL loader items
- total data items hasil query
Ini sangat membantu untuk:
- memastikan query benar
- memastikan join template match
- memastikan data memang ada di DB
14.3 Debug WordPress yang direkomendasikan
Kalau butuh pelacakan lebih dalam (misalnya issue production yang intermittent), aktifkan log WP:
Di wp-config.php:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Lalu cek file:
Praktik yang bagus:
- saat error terjadi, ambil 30 sampai 80 baris terakhir dari debug.log
- cocokkan timestamp, lalu telusuri query atau fungsi mana yang memicu error
15) Catatan Implementasi Teknis Penting di File Ini
Beberapa helper DB dibuat di dalam halaman supaya halaman tetap kuat walau environment berbeda:
wb_db_one(), ambil 1 row
wb_db_all(), ambil banyak row
wb_db_exec(), eksekusi query prepared statement
wb_stmt_bind_safe(), binding param aman, mencegah fatal error mismatch jumlah tipe dan variabel
wb_tbl_exists(), wb_col_exists(), deteksi tabel dan kolom dinamis, supaya backward compatible saat tabel berubah
Tujuan desain ini:
- mengurangi kemungkinan “critical error”
- lebih toleran terhadap variasi struktur kolom antar environment
16) Checklist Pengujian, QA Manual
Gunakan checklist ini setelah ada perubahan apapun.
A. Read-only
- Buka halaman dengan lead valid yang sudah punya roadmap
- Pastikan items muncul dan terbagi per stage yang sesuai
- Pastikan join template menampilkan title dan message
B. Generate roadmap awal
- Buat lead baru tanpa item roadmap
- Pastikan panel generate muncul
- Pilih group, klik Generate
- Pastikan redirect sukses dan jumlah item sesuai template
- Pastikan tidak bisa generate ulang (harus muncul warning)
C. Lihat teks dan Copy
- Klik dropdown item, pilih “Lihat teks”
- Modal muncul, teks terisi
- Tombol Copy berfungsi
- Pastikan tetap jalan walau Bootstrap modal gagal (fallback)
D. WhatsApp
- Pastikan tombol WhatsApp muncul jika nomor valid
- Pastikan link wa.me terbuka dan teks sudah berisi nama lead (token terisi)
E. Mark sent / skip
- Tandai terkirim, status berubah sent
- Skip, status berubah skipped
- Progress bar berubah sesuai
F. Generate next stage
- Selesaikan semua item purchase, status sent atau skipped
- Tombol generate retention muncul
- Klik generate retention, item retention tercipta, stage lead berubah retention
- Lakukan hal sama untuk advocacy
17) Ekstensi yang Disarankan (Jika Mau Naik Level)
Kalau nanti kamu mau membuat sistem ini makin “siap operasional tim”, pengembangan yang paling masuk akal:
- Simpan
freebie_link ke data lead atau ke lead magnet, lalu render token itu otomatis
- Tambahkan “note per item” yang bisa diisi di UI sebelum mark sent, untuk mencatat respon lead
- Tambahkan filter, hari ini, minggu ini, overdue, untuk operasional follow up harian
- Tambahkan audit log, siapa yang mark sent, kapan, dari user mana
- Tambahkan “reschedule”, ubah scheduled_at per item tanpa mengubah template
- Tambahkan tombol “copy to clipboard + open WA” otomatis untuk mempercepat eksekusi
18) Ringkasan untuk Pembaca Baru
Jika kamu baru pertama kali melihat sistem ini, ingat 3 hal:
- Template follow up disiapkan dulu di Master, lalu dikelompokkan dengan Followup Template Group.
- Halaman ini mengubah template menjadi item roadmap nyata untuk lead tertentu, lengkap dengan jadwal dan status.
- Operasionalnya manual, tetapi terstruktur, tinggal klik lihat teks, copy, kirim WA, lalu tandai terkirim.