bebas.kompas.id
Membangun corong akuisisi pengguna untuk media digital surat kabar terbesar di Indonesia
Teknologi: WordPress, Timber (Twig), Vue.js 2, Vuex, Tailwind CSS, Webpack, ACF, REST API, Google Analytics, GTM
Saya bertanggung jawab penuh atas arsitektur frontend dan sistem konversi di bebas.kompas.id. Saya bekerja erat dengan tim redaksi, pemasaran, dan pengembang sisi backend. Sebagai kontributor utama (±57% dari total commit dalam tim inti beranggotakan 2 orang), saya mengambil sejumlah keputusan arsitektural penting yang menentukan bagaimana platform menyeimbangkan optimasi mesin pencari (SEO), performa, dan optimasi konversi.
Tantangan Strategis
Pada 2018, kompas.id menghadapi dilema strategis. Sebagai platform berita premium berbayar, mereka harus bersaing dengan media gratis tanpa mengorbankan pendapatan langganan. Solusinya adalah membangun bebas.kompas.id, sebuah platform terpisah berisi artikel-artikel bebas-baca yang berfungsi sebagai corong akuisisi pengguna.
Kebutuhannya jelas:
Editor menentukan artikel bebas-baca, bukan algoritma atau buka akses berbasis waktu
Masa tayang 7 hari, setelah itu pembaca otomatis dialihkan ke halaman berlangganan kompas.id
Alur konversi yang mulus, dari pembaca gratis ke pelanggan berbayar
Arsitektur mengutamakan SEO, konten harus mudah diindeks dan cepat dimuat
Performa di jaringan seluler Indonesia, tempat 3G masih dominan di luar kota besar
Keputusan Arsitektur: "Islands of Interactivity" (Pulau Interaktivitas)
Saya memilih arsitektur hibrida berbasis “islands”: WordPress + Timber (Twig) untuk render sisi server, dengan Vue.js menangani komponen interaktif secara terisolasi. Pendekatan ini diterapkan bahkan sebelum framework seperti Astro memopulerkan pola tersebut. Kami menemukannya melalui desain berbasis batasan teknis (constraint-driven design).
Mengapa tidak menggunakan SPA sepenuhnya?
SEO tidak bisa ditawar. HTML hasil render server langsung bisa diindeks Google
Ekosistem kompas.id berbasis WordPress, integrasi harus selaras dengan alur kerja redaksi
Jaringan mobile Indonesia menuntut JavaScript seminimal mungkin. SPA sepenuhnya akan mematikan performa di luar Jakarta
Mengapa bukan WordPress murni?
Alur konversi memerlukan pengelolaan status secara waktu nyata. Saat user tercatat masuk (log in), tampilan antarmuka harus langsung bereaksi tanpa memuat ulang halaman
A/B testing memerlukan penentuan eksperimen di sisi klien (client-side). Jika dilakukan hanya di sisi server (server-side), hal itu akan menjadi mimpi buruk bagi pengelolaan tembolok (cache-busting).
Komponen interaktif (sticky header, share tools, dan baner onboarding) butuh reaktivitas yang tidak bisa ditangani kode 'spageti' jQuery
Hasil: Kombinasi Terbaik Keduanya
┌─────────────────────────────────────────────────────────┐
│ Browser │
└─────────────────────────┬───────────────────────────────┘
│ Request
▼
┌─────────────────────────────────────────────────────────┐
│ WordPress + Timber (PHP) │
│ Server-renders HTML with article content │
│ SEO-ready, cacheable, fast │
└─────────────────────────┬───────────────────────────────┘
│ HTML + embedded data
▼
┌─────────────────────────────────────────────────────────┐
│ Vue.js Hydration (Client) │
│ "Islands" of interactivity mount on static HTML │
│ Header, Share Tools, Onboarding Banners, Paywall UI │
└─────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Vuex Store │
│ User state, membership, UI preferences │
│ Enables instant UI response to auth changes │
└─────────────────────────────────────────────────────────┘Dengan arsitektur ini, editor bisa menerbitkan 10+ artikel per hari tanpa keterlibatan pengembang—tanpa build, tanpa deploy, tanpa hambatan frontend.
Merancang untuk Kegagalan: Degradasi Terkontrol
Dalam bisnis berbasis langganan, kegagalan otentikasi langsung berdampak ke pendapatan. Jika pengecekan keanggotaan gagal dan antarmuka pengguna rusak, pelanggan tidak bisa membaca dan calon pelanggan tidak melihat ajakan konversi. Keduanya berujung pada kerugian finansial.
Arsitektur bebas.kompas.id memiliki ketergantungan kritis, yakni Vuex user store mengambil status keanggotaan dari sebuah endpoint PHP pada setiap pemuatan halaman. Jika endpoint tersebut gagal (karena masalah jaringan, kelebihan beban server, atau kesalahan konfigurasi), seluruh alur konversi bisa terhenti total.
Pendekatan defensif: Alih-alih membiarkan kesalahan merambat, store dirancang untuk gagal secara terkontrol dengan menetapkan status awal sebagai "keluar" (logged out) jika pemeriksaan otentikasi gagal. Dampaknya:
Halaman tetap tampil (tidak kosong)
Calon pelanggan tetap melihat ajakan konversi (pendapatan terlindungi)
Pelanggan mendapat pengalaman terdegradasi (tanpa personalisasi), bukan halaman rusak
// Defensive user state management
const actions = {
async fetch({ commit, state }) {
try {
const { data } = await axios.get(endpoint)
commit('setUser', data)
commit('setIsLoading', false)
} catch (error) {
// Graceful degradation: assume logged-out, don't break the page
commit('setUser', { membership: null })
commit('setIsLoading', false)
// Silent failure > broken page
console.error('Auth endpoint failed:', error.message)
}
}
}Risiko: Pelanggan yang mengalami kegagalan pemeriksaan otentikasi akan melihat baner onboarding yang seharusnya tidak muncul. Itu memang pengalaman pengguna yang buruk, tetapi masih bisa diperbaiki (cukup muat ulang halaman). Sebaliknya, layar putih kosong atau galat JavaScript tidak dapat diperbaiki oleh pengguna.
Sistem Utama yang Dibangun
1. Mesin Akses Gratis Berbatas Waktu
Masalah: Editor menginginkan artikel tersedia secara gratis selama tepat 7 hari, kemudian dialihkan (redirect) ke halaman berlangganan kompas.id. Mengelola pengalihan secara manual untuk lebih dari 10 artikel setiap harinya tidak mungkin dilakukan secara berkelanjutan.
Solusi: Membangun sistem kalkulasi usia artikel di sisi server yang berjalan pada setiap permintaan artikel. Artikel berusia lebih dari 7 hari akan mengembalikan status 302 redirect ke URL padanannya di kompas.id.
private function redirect_if_necessary() {
$today = Carbon::now('Asia/Jakarta');
$publish_date = Carbon::parse($post->post_date_gmt)->tz('Asia/Jakarta');
$diff_date = $publish_date->diffInDays($today);
// 302 (not 301) preserves SEO link equity for the destination
if ($diff_date > 7) {
$redirect_url = str_replace('bebas.kompas.id', 'kompas.id', get_permalink());
wp_redirect($redirect_url, 302);
exit;
}
}Mengapa 302 dan bukan 301? Penggunaan 301 akan memindahkan nilai SEO secara permanen dari bebas.kompas.id. Dengan 302, kami menjaga peringkat pencarian pada corong tersebut sambil tetap mengalihkan pengguna.
Hasil: Tidak diperlukan intervensi manual sama sekali. 100% artikel bertransisi dengan benar selama 18 bulan operasional.
2. Mesin Marketing Terpisah (Sistem Onboarding)
Masalah: Tim pemasaran perlu menjalankan eksperimen konversi setiap minggu, tetapi jalur deployment kami memakan waktu lebih dari 2 jam. Mereka tidak bisa melakukan iterasi dengan cukup cepat untuk teks baner, tombol ajakan (CTA), atau kampanye promosi.
Solusi: Membangun sistem baner berbasis REST API tempat tim pemasaran mengontrol segalanya melalui admin WordPress (ACF). Komponen Vue mengambil konfigurasi saat halaman dimuat sehingga perubahan kampanye sama sekali tidak memerlukan deployment.
// Banner component fetches live configuration
async get_settings() {
const { data } = await axios.get(
'/wp-json/kompas/v1/theme/settings/banners/onboardings/single'
)
// Respect campaign scheduling (start/end dates set by marketing)
const now = Date.parse(data.bottom.now)
const start = Date.parse(data.bottom.start_airing)
const end = Date.parse(data.bottom.finished_airing)
if (now >= start && now <= end) {
this.item = data // Show banner
} else {
this.item = null // Campaign not active
}
}Keunggulan utama: Tim pemasaran bisa menjadwalkan kampanye berminggu-minggu sebelumnya. Skenario seperti "Promo Black Friday dimulai 25 November tengah malam" dapat berjalan otomatis, tanpa perlu pengembang berjaga tengah malam.
Hasil: Tim pemasaran berhasil menjalankan lebih dari 15 eksperimen konversi dalam 6 bulan (dibandingkan hanya 2-3 eksperimen pada tahun sebelumnya dengan alur kerja lama).
3. Arsitektur Konten Multi-format
Masalah: Jurnalis Kompas memproduksi empat jenis konten yang berbeda, yaitu artikel standar, galeri foto, foto cerita (narasi visual), dan artikel video. Masing-masing memiliki kebutuhan tata letak dan perilaku interaktif yang berbeda.
Solusi: Membangun sistem perutean (routing) template yang mendeteksi jenis konten melalui kategori WordPress, kemudian me-render template Twig yang sesuai dengan komponen Vue yang telah dipadankan.
// Content-type routing in single.php
if ($context['post_has_galeri_foto']) {
// Photo gallery: Vue lightbox component, image lazy-loading
Timber::render('single/single-has-galeri-foto.twig', $context);
} elseif ($context['post_has_foto_cerita']) {
// Photo story: immersive scroll-driven layout
Timber::render('single/single-has-foto-cerita.twig', $context);
} elseif ($context['post_has_video']) {
// Video article: custom Kompas Video player integration
Timber::render('single/single-has-video.twig', $context);
} else {
// Standard article with A/B test tracking
Timber::render('single/single.twig', $context);
}Hasil: Editor dapat menerbitkan jenis konten apa pun tanpa perlu memikirkan "kebutuhan frontend." Sistem menangani semuanya secara otomatis.
4. Infrastruktur Penelusuran Konversi & A/B Testing
Masalah: Kami perlu memahami konten, tata letak, dan CTA mana yang mendorong angka langganan. Namun, kami tidak bisa melacak semuanya di sisi server tanpa merusak sistem tembolok (cache-busting).
Solusi: Penentuan eksperimen dilakukan di sisi klien melalui GTM, dengan Vuex yang mengelola state eksperimen tersebut. Setiap titik sentuh konversi (klik login, klik daftar, tampilan paywall) memicu even pelacakan yang dilengkapi dengan parameter UTM.
// Experiment assignment on component mount
mounted() {
this.$nextTick(() => {
ga('set', 'exp', window.kompas_gtm_vars.exp_type)
ga('send', { hitType: 'pageview' })
})
}
// Conversion tracking with full attribution
gaSend(e, action) {
const params = new URLSearchParams({
utm_source: 'kompasid',
utm_medium: `${action}_paywall`,
utm_campaign: action,
utm_content: this.uri
})
ga('send', 'event', action, 'click', window.kompas_local_vars.permalink, {
hitCallback: () => {
window.location.href = `${this.signInLink}?next=${this.uri}&${params}`
}
})
}Hasil: Tim pemasaran akhirnya bisa menjawab pertanyaan "teks baner mana yang menghasilkan konversi lebih baik?" berdasarkan data, bukan sekadar opini.
5. Lapisan Antarmuka Pengguna Berbasis Status Keanggotaan
Masalah: Pengguna tidak berlangganan perlu melihat ajakan konversi, sementara pelanggan harus mendapatkan pengalaman membaca yang bersih. Tampilan antarmuka harus berubah secara instan saat status otentikasi berubah tanpa muat ulang halaman.
Solusi: Store Vuex menyimpan status keanggotaan yang diambil saat halaman dimuat. Semua komponen antarmuka konversi bersifat reaktif terhadap status ini.
<template>
<!-- Only show onboarding banner to non-subscribers -->
<div v-if="!membership || membership === undefined">
<OnboardingBanner :expired-at="expiredAt" />
</div>
<!-- Subscribers see clean reading experience -->
<div v-else class="subscriber-content">
<slot />
</div>
</template>
<script>
import { mapState, mapGetters } from 'vuex'
export default {
computed: {
...mapState({
membership: state => state.user.user.membership
}),
...mapGetters({
is_loading: 'user/is_loading'
})
}
}
</script>Hasil: Saat pengguna masuk (login) melalui SSO dari kompas.id), halaman tidak dimuat ulang. Secara mulus baner menghilang dan fitur khusus pelanggan langsung muncul.
Pembelajaran Penting: Psikologi Konversi
Membangun corong langganan mengajarkan saya hal-hal yang tidak pernah dibahas dalam tutorial mana pun:
Kedalaman gulir (scroll depth) lebih penting daripada durasi di halaman (time-on-page).
Pengguna yang menggulir lebih dari 60% artikel sebelum melihat ajakan berlangganan memiliki tingkat konversi lebih baik ketimbang mereka yang melihatnya segera. Kami pun menyesuaikan kemunculan baner berdasarkan data tersebut.“Gratis selama 7 hari” menciptakan urgensi nyata.
Penghitung waktu mundur di baner bawah ("Artikel ini gratis hingga [tanggal]") memiliki performa lebih baik daripada pesan umum seperti "Berlangganan sekarang".Foto cerita menarik perhatian, tetapi tidak mendorong konversi.
Konten visual memiliki tingkat interaksi 18% lebih tinggi (kedalaman gulir, durasi di halaman), tetapi tingkat konversinya lebih rendah. Hipotesis kami: pengguna hanya menginginkan konten visual gratis, bukan berlangganan. Kami akhirnya menyesuaikan teks CTA khusus untuk format ini.Hambatan saat catat masuk mematikan konversi.
Setiap klik tambahan antara "Saya ingin berlangganan" hingga "Saya di halaman pembayaran" mengakibatkan hilangnya calon pelanggan. Kami mengoptimalkan rantai pengalihan (redirect chain) ini secara obsesif.
Dampak & Skala
bebas.kompas.id rilis awal 2019 dan menjadi saluran akuisisi utama Kompas:
Kecepatan editorial: 10+ artikel/hari tanpa deployment dari sisi frontend
Kelincahan pemasaran: Perubahan kampanye dapat diterapkan dalam hitungan menit, bukan jam.
Fondasi teknis: Arsitektur mampu mendukung iterasi selama 18+ bulan tanpa perlu perombakan besar.
Pemberdayaan tim: Fitur-fitur selanjutnya (iklan responsif, embed video, integrasi Twitter) dibangun menggunakan pola yang saya tetapkan.
Platform ini terus beroperasi hingga tahun 2020 ke atas, dengan tim yang terus mengembangkannya berdasarkan arsitektur hibrida yang saya rancang.
Keputusan Teknis yang Akan Saya Ubah
Menggunakan Nuxt.js sejak awal
Arsitektur hibrida Vue + Timber berfungsi, tetapi Nuxt dengan SSR akan menyederhanakan proses hidrasi dan perutean. Pada praktiknya, kami membangun versi Nuxt secara manual.Menerapkan penanda fitur (feature flags)
Proses rilis dan peluncuran fitur masih saling terikat. Penanda fitur memungkinkan pengiriman kode berkelanjutan dengan kontrol aktivasi terpisah.Instrumentasi analitik yang lebih dalam
Kami melacak konversi, tetapi tidak melacak perilaku mikro yang mengarah ke sana. Data segmentasi kedalaman gulir, durasi kursor di atas baner, hingga latensi antara hover ke klik pada CTA akan memungkinkan optimasi yang jauh lebih halus.
Tim & Kontribusi
Saya adalah kontributor utama dengan sekitar 57% dari total commit. Proyek ini pada dasarnya dibangun oleh tim inti yang terdiri dari 2 orang. Saya memimpin arsitektur dan implementasi frontend.
Tentang Proyek Ini
bebas.kompas.id adalah platform berita bebas akses dari PT Kompas Media Nusantara, yang dirancang untuk melengkapi layanan premium berbayar kompas.id. Platform ini berfungsi sebagai corong akuisisi pengguna, yang memungkinkan pembaca mencoba jurnalisme berkualitas sebelum memutuskan untuk berlangganan.
Keputusan arsitektur yang dibuat di sini—hibrida SSR/CSR, sistem pemasaran terpisah (decoupled), tampilan antarmuka yang reaktif terhadap keanggotaan—mencerminkan batasan serta peluang dalam membangun media skala besar di Indonesia.
Like what you see?
I'm open to freelance projects and full-time roles. If you need someone who obsesses over structure and ships clean code — let's talk.
:quality(70))