AL

HowIBuiltanAutomatedNetflixSubscriptionReminderviaWhatsAppforUnder$0
DateApril 06, 2026

Because manually texting 20 people every month is not a vibe.

The Problem

My friend manage a shared Netflix account for a bunch of people. Every month, he have to manually message each person reminding them to pay. Sometimes he forget. Sometimes they'd forget. It was chaos.

So I did what any developer would do to help him. I spent time automating it instead of just doing it manually. Worth it.

What I Wanted to Build

A system that:

  • Reads subscriber data from Google Sheets
  • Automatically calculates when each person's payment is due
  • Sends WhatsApp reminders at H-3, H-1, due date, and H+1 (overdue)
  • Costs as close to $0 as possible
  • Runs on my homeserver with zero manual intervention

The Stack (and Why)

Here's what I ended up with:

  • Google Sheets, already where I track everything. No new tools needed.
  • Google Apps Script, free, runs in the cloud, can hit external APIs. Perfect for the automation logic.
  • Go WhatsApp Web Multidevice (GoWA), a lightweight Go-based self-hosted WhatsApp API. No monthly fees, no third-party services, runs on my homeserver with ~50MB RAM.
  • Cloudflare Tunnel, exposes my homeserver to the internet for free, no port forwarding needed.

Setting Up GoWA

GoWA is stupid simple to get running. One command:

Bash
1wget https://github.com/aldinokemal/go-whatsapp-web-multidevice/releases/latest/download/whatsapp-linux-amd64 -O whatsapp && \
2chmod +x whatsapp && \
3sudo mv whatsapp /usr/local/bin/gowa && \
4sudo bash -c 'cat > /etc/systemd/system/gowa.service << EOF
5[Unit]
6Description=Go WhatsApp Web
7After=network.target
8
9[Service]
10ExecStart=/usr/local/bin/gowa --port 3001
11Restart=always
12User='$USER'
13
14[Install]
15WantedBy=multi-user.target
16EOF' && \
17sudo systemctl daemon-reload && \
18sudo systemctl enable gowa && \
19sudo systemctl start gowa

Then open http://localhost:3001, scan the QR code, and you're connected.

gowa
gowa

Exposing the Homeserver with Cloudflare Tunnel

Google Apps Script runs on Google's servers — it can't reach localhost. So I used Cloudflare Tunnel to give GoWA a public HTTPS URL for free.

Bash
1cloudflared tunnel login 
2cloudflared tunnel create gowa 
3cloudflared tunnel route dns gowa wa.yourdomain.com 
4cloudflared tunnel run gowa

Now GoWA is accessible at https://wa.yourdomain.com from anywhere.

Google Sheets Structure

Simple. Four columns:

Markdown
1Nama	 No WA	 Tgl Bayar Terakhir	 Status
2Budi	 62812xxx	 01/03/2026	 Aktif

The Status column is auto-calculated:

Markdown
1=IF(ISBLANK(C2),"-",IF(TODAY()-C2<30,"Aktif","Nonaktif"))

No manual status updates needed — it flips automatically based on the last payment date.

List Customer on Spreadsheet
List Customer on Spreadsheet

The Brain: Google Apps Script

This is where the magic happens. The script:
1. Reads all rows from the sheet
2. Calculates the next billing date (last payment + 30 days)
3. Checks if today is H-3, H-1, due date, or H+1
4. Sends a WhatsApp message via GoWA if it matches

Javascript
1const CONFIG = {
2  GOWA_URL: 'https://wa.yourdomain.com',
3  GOWA_USER: 'admin',
4  GOWA_PASS: 'your-password',
5  DEVICE_ID: 'default',
6  SHEET_NAME: 'Sheet1',
7  REMINDER_DAYS: [3, 1, 0, -1]
8}
9
10function cekTagihan() {
11  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(CONFIG.SHEET_NAME)
12  const data = sheet.getDataRange().getValues()
13  const today = new Date()
14  today.setHours(0, 0, 0, 0)
15
16  for (let i = 1; i < data.length; i++) {
17    const nama        = data[i][0]
18    const noWa        = data[i][1].toString()
19    const tglBayarRaw = data[i][2]
20    const status      = data[i][3]
21
22    if (status !== 'Aktif') continue
23
24    const tglBayar = new Date(tglBayarRaw)
25    if (isNaN(tglBayar.getTime())) continue
26
27    tglBayar.setHours(0, 0, 0, 0)
28    const tglTagihan = new Date(tglBayar)
29    tglTagihan.setDate(tglTagihan.getDate() + 30)
30
31    const selisih = Math.round((tglTagihan - today) / (1000 * 60 * 60 * 24))
32
33    if (!CONFIG.REMINDER_DAYS.includes(selisih)) continue
34
35    let tipe
36    if (selisih === 3)       tipe = 'H-3'
37    else if (selisih === 1)  tipe = 'H-1'
38    else if (selisih === 0)  tipe = 'Hari-H'
39    else if (selisih === -1) tipe = 'Telat'
40
41    const pesan = formatPesan(nama, tipe, tglTagihan)
42    kirimWA(noWa, pesan)
43    Utilities.sleep(1000)
44  }
45}
Google Apps Script
Google Apps Script

The WhatsApp Messages

Each reminder type has its own message template:

H-3:

Halo Budi! 👋
Reminder Netflix kamu akan jatuh tempo 3 hari lagi (04/04/2026).
Jangan lupa perpanjang ya! 🙏

Overdue:

Halo Budi! 🔴
Tagihan Netflix kamu sudah melewati jatuh tempo (04/04/2026).
Hubungi admin untuk perpanjang.
WA Messages
WA Messages

Setting the Trigger

In Apps Script → Triggers → Add Trigger:

  • Function: cekTagihan
  • Event: Time-driven → Day timer → 8am–9am

GAS doesn't support exact-time triggers, but an 8–9am window is good enough for payment reminders.

Google Apps Script Trigger
Google Apps Script Trigger

Final Architecture

Google Sheets (subscriber data) → Google Apps Script (runs daily 8–9am) → HTTPS Cloudflare Tunnel → GoWA on Homeserver (port 3001) → WhatsApp

Total cost: $0/month (assuming you already have a homeserver).

What I'd Improve Next

  • Add a "Sudah Bayar" button that auto-updates the last payment date
  • Track payment history per subscriber
  • Send reminders via Telegram as a fallback
  • Move config to a dedicated Settings sheet so non-devs can update it

Wrapping Up

This took a few hours to build but saves my friends from manual messaging every single month. The stack is boring in the best way. No paid services, no complex infra, just a few free tools stitched together.

If you're managing a shared account or running a small subscription business, this approach works surprisingly well.

Temanggung, Indonesia

© Alvin Al - 2026