2026.06.09 (Sel)

โœจ Ringkasan GPT-5.5 ใ€€

Catatan tentang melacak lonjakan aneh pada visitor counter, mencegah kerja lokal ikut terhitung, dan menambahkan halaman analytics agregat publik dengan Cloudflare Worker dan D1.

Visitor counter terlihat aneh.

Jumlah harian tiba-tiba melewati 80.

Awalnya bisa saja dianggap sebagai traffic dari pencarian. Tapi rasanya tidak pas. Beberapa hari terakhir aku banyak memperbaiki blog, dan selama kerja dengan AI aku juga sering membuka server lokal dan URL publik.

Jadi pertanyaannya jelas.

Apakah ini traffic sungguhan?

Atau pekerjaanku sendiri ikut dihitung?

Counternya terlalu jujur

Aku mengecek lagi strukturnya.

Counter yang dibuat di /id/devlog/github-pages-blog/github-pages-blog-visitor-counter/ memakai Cloudflare Worker dan D1.

Saat halaman dimuat, JavaScript mengirim /track ke Worker. Worker menaikkan counters, page_counters, dan dedupe_views di D1. Google Analytics hanya dipakai sebagai baseline; increment baru disimpan di D1.

Masalahnya, struktur ini terlalu jujur.

Kalau browser membuka halaman, itu dihitung.

Server lokal juga mengarah ke Worker produksi. Origin yang diizinkan Worker juga berisi localhost:4000 dan 127.0.0.1:4000.

Artinya preview lokal pun bisa menaikkan counter produksi yang asli.

Deduplication juga memakai visitorId + path. Halaman yang sama di browser yang sama didedupe selama 10 menit, tetapi membuka banyak post berbeda tetap menghitung semuanya.

D1 memperlihatkannya dengan jelas.

day:2026-06-06 = 14
day:2026-06-07 = 38
day:2026-06-08 = 81
day:2026-06-09 = 5

Pada 2026-06-08, banyak Daily Review lama dan post naver-* tersentuh satu per satu. Itu lebih mirip sesi pengecekan kerja daripada pembaca sungguhan.

Kerja lokal boleh menampilkan, tetapi tidak menghitung

Perbaikan pertama sederhana.

Di lokal, statistik boleh tampil, tetapi /track tidak boleh dikirim.

localhost
127.0.0.1
::1

Di lingkungan ini, script client melewati tracking.

Tapi mengandalkan client saja rapuh. Kalau JS berubah atau ada request manual, masalah yang sama bisa kembali. Jadi Worker juga hanya menghitung /track dari production origin.

TRACK_ALLOWED_ORIGIN=https://hyuk.blog

Request dari origin lokal sekarang diabaikan dengan origin_not_tracked.

Aku juga menambahkan opt-out untuk mengecek production tanpa mengotori counter.

?hyuk_no_track=1
?visitor_tracking=off
?visitor_tracking=on

Ini bukan fitur admin tersembunyi. Ini hanya switch agar aku bisa mengecek halaman publik tanpa mengubah angka.

Statistik tidak harus disembunyikan

Awalnya aku berpikir membuat halaman analytics pribadi.

Tapi ternyata tidak perlu.

Kalau tidak menyimpan raw IP, raw User-Agent, full referrer URL, atau log event per request, halaman itu bisa publik. Cukup simpan nilai agregat yang aman ditampilkan.

Jadi arahnya berubah.

Bukan halaman log privat.

Melainkan halaman statistik blog publik.

/analytics/

Aku menambahkannya ke navigasi atas dan juga dari blok visitor stats kecil di sidebar.

D1 hanya menyimpan agregat

Tabel barunya sederhana.

analytics_daily_dimensions

date
dimension
value
count
updated_at

Saat page view benar-benar dihitung, Worker mengklasifikasikan dimensi publik dan menambah agregat harian.

Dimensi yang dikumpulkan:

page
content_group
locale
country
region
continent
colo
asn_org
device
viewport
browser
os
language
client_timezone
color_scheme
connection
traffic_source
referrer_domain
hour
weekday

Yang penting adalah apa yang tidak disimpan.

Referrer disimpan sebagai domain, bukan URL lengkap. User-Agent tidak disimpan mentah, tetapi diklasifikasikan menjadi browser, OS, dan device. IP tidak disimpan.

Ini bukan gudang analytics yang ketat. Ini panel alur publik untuk blog pribadi.

Hari ini, bulan, total, dan rentang khusus

Awalnya aku hanya memikirkan hari ini / bulan / total, seperti counter yang sudah ada.

Tapi halaman statistik perlu rentang tanggal.

API /analytics menerima:

/analytics?range=today
/analytics?range=month
/analytics?range=total
/analytics?range=custom&start=2026-06-09&end=2026-06-12

Di sini, total berarti total sejak analytics_daily_dimensions mulai mengumpulkan data pada 2026-06-09. Ini berbeda dari total di sidebar, yang masih menyertakan baseline GA.

Dua makna itu tidak dicampur.

Mobile dulu supaya benar-benar bisa dipakai

Halaman statistik mudah rusak di mobile.

Tabel besar cepat terasa sesak. Jadi aku memakai kartu berisi daftar bar.

Di bagian atas hanya ada empat angka.

Rentang terpilih
Hari ini
Bulan ini
Total

Di bawahnya ada kartu untuk tiap dimensi.

Di mobile, tombol rentang menjadi dua baris, KPI menjadi dua kolom, dan semua kartu detail turun menjadi satu kolom. Form rentang khusus juga tersusun vertikal.

Di desktop, KPI tetap satu baris dan kartu detail menjadi dua kolom.

Aku memeriksanya di browser. Tidak ada horizontal overflow dan tidak ada console error.

Yang diverifikasi

Pemeriksaannya:

node --check cloudflare/ga-stats-worker.js
node --check assets/js/custom/visitor-stats.js
node --check assets/js/custom/analytics-dashboard.js
bundle exec jekyll build
npx wrangler d1 execute hyuk-blog-view-counter --remote --file cloudflare/schema.sql
npx wrangler deploy --keep-vars

Setelah deploy, /analytics?range=today merespons normal.

Tabel agregat baru masih kosong. Itu wajar. Analytics detail baru mulai terisi dari kunjungan publik nyata setelah deploy.

Aku juga menguji tracking dari origin lokal.

{"status":"ignored","reason":"origin_not_tracked"}

Sekarang pengecekan blog di lokal tidak menaikkan counter produksi.

Dari visitor counter ke analytics publik

Awalnya hanya tiga angka kecil.

Hari ini, bulan, total.

Tapi setelah benar-benar dioperasikan, yang penting bukan hanya angkanya. Yang penting adalah apakah angkanya bersih. Dan untuk blog publik, menampilkan alur agregat yang aman lebih cocok daripada menyembunyikan halaman log privat.

Ini bukan pembukuan yang presisi.

Tapi sekarang bisa menjawab pertanyaan yang lebih berguna.

Post mana yang dibaca?

Dari negara mana orang masuk?

Lebih banyak mobile atau desktop?

Traffic dari search, direct, atau referral?

Dan yang paling penting, seberapa jauh noise dari pekerjaanku sendiri harus dikeluarkan?

Itulah fungsi /analytics/.

Tinggalkan komentar