Full width home advertisement

My Project

Data Analyst

Post Page Advertisement [Top]

Bayangkan ini: setiap Senin pagi, laporan mingguan tim sudah tersaji rapi di inbox—lengkap dengan ringkasan tren, anomali data, dan rekomendasi singkat—tanpa ada satu pun manusia yang menyentuh keyboard untuk membuatnya. Bukan sihir. Bukan pula butuh tim engineering besar. Cukup Google Sheets, Apps Script, dan akses ke ChatGPT API.

Bagi seorang Analytics Engineer atau Ops yang sudah terbiasa membangun pipeline data, otomasi laporan mingguan bukan sekadar penghematan waktu—ini soal memastikan konsistensi, mengurangi human error, dan membebaskan bandwidth mental untuk pekerjaan yang benar-benar butuh pertimbangan manusia. Artikel ini akan memandu kamu melewati framework end-to-end untuk membangun sistem ini dari nol.

Sebelum masuk ke teknisnya, penting dipahami bahwa pendekatan ini tidak membutuhkan server eksternal, tidak butuh subscription SaaS mahal, dan bisa berjalan sepenuhnya dalam ekosistem Google Workspace yang sudah kamu gunakan sehari-hari. Yang dibutuhkan hanyalah pemahaman tentang cara kerja masing-masing komponen dan bagaimana menghubungkannya secara terstruktur.

Mengapa Framework, Bukan Sekadar Script?

Banyak tutorial otomasi berhenti di level "copy-paste script dan jalankan". Masalahnya, script tanpa struktur adalah bom waktu. Ketika data berubah format, ketika API limit tercapai, atau ketika tim butuh menambah kolom baru di laporan—sistem yang dibangun tanpa framework akan runtuh dan kamu harus membangun ulang dari awal.

Framework yang dibahas di sini dibangun di atas tiga prinsip utama:

  • Modularitas — setiap fungsi punya tanggung jawab tunggal dan bisa diuji secara independen
  • Resiliensi — ada error handling di setiap titik integrasi, terutama di layer API call
  • Observabilitas — sistem mencatat log aktivitasnya sendiri ke sheet terpisah, sehingga kamu tahu persis apa yang terjadi tanpa harus debugs secara manual

Gambaran Arsitektur Sistem

Sebelum menulis satu baris kode pun, visualisasikan dulu seluruh alur sistemnya. Ini adalah peta kerja yang akan menjadi acuan selama proses pembangunan.

Layer Komponen Fungsi
Data Source Google Sheets (Tab: Raw Data) Tempat data mentah mingguan tersimpan
Processing Apps Script — fungsi aggregateData() Membaca, membersihkan, dan merangkum data menjadi teks konteks
AI Layer Apps Script — fungsi callChatGPT() Mengirim konteks ke ChatGPT API dan menerima narasi laporan
Output Google Sheets (Tab: Laporan) + Email Menyimpan hasil dan mendistribusikan laporan ke tim
Scheduler Apps Script Time-driven Trigger Menjalankan seluruh pipeline otomatis setiap Senin pukul 07.00
Monitoring Google Sheets (Tab: System Log) Mencatat setiap eksekusi, status, dan error yang terjadi

Langkah 1 — Siapkan Struktur Google Sheets

Efisiensi sistem ini sangat bergantung pada struktur spreadsheet yang bersih dan konsisten. Buat satu file Google Sheets dengan empat tab berikut:

  1. Raw Data — kolom standar: Tanggal, Kategori, Metrik, Nilai, Catatan
  2. Config — tempat menyimpan API Key, nama tim, parameter prompt, dan alamat email penerima
  3. Laporan — output narasi dari ChatGPT akan dituliskan di sini, lengkap dengan timestamp
  4. System Log — log otomatis setiap kali script dijalankan

Alasan memisahkan Config ke tab tersendiri sangat krusial: kamu bisa mengubah API Key atau daftar penerima email tanpa harus menyentuh kode sama sekali. Ini menjadikan sistem dapat dikelola oleh siapapun di tim, bahkan yang tidak paham coding.

Langkah 2 — Bangun Fungsi Inti di Apps Script

Buka Apps Script dari menu Extensions → Apps Script. Struktur kode dibagi menjadi tiga modul utama yang masing-masing punya file terpisah untuk kemudahan pemeliharaan.

Modul 1: Pembaca Data dan Agregator

Rumus/Function: aggregateData()
function aggregateData() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const rawSheet = ss.getSheetByName("Raw Data");
  const configSheet = ss.getSheetByName("Config");
 
  // Ambil data minggu ini (7 hari terakhir)
  const today = new Date();
  const sevenDaysAgo = new Date(today - 7 * 24 * 60 * 60 * 1000);
 
  const allData = rawSheet.getDataRange().getValues();
  const headers = allData[0];
  const rows = allData.slice(1);
 
  // Filter hanya data 7 hari terakhir
  const weeklyData = rows.filter(row => {
    const rowDate = new Date(row[0]);
    return rowDate >= sevenDaysAgo && rowDate <= today;
  });
 
  // Buat ringkasan per kategori
  const summary = {};
  weeklyData.forEach(row => {
    const kategori = row[1];
    const nilai = parseFloat(row[3]) || 0;
    if (!summary[kategori]) summary[kategori] = { total: 0, count: 0 };
    summary[kategori].total += nilai;
    summary[kategori].count += 1;
  });
 
  // Format sebagai teks konteks untuk dikirim ke ChatGPT
  let konteks = `Laporan minggu ${Utilities.formatDate(sevenDaysAgo, "Asia/Jakarta", "dd MMM")} - ${Utilities.formatDate(today, "Asia/Jakarta", "dd MMM yyyy")}:\n\n`;
  
  for (const [kategori, data] of Object.entries(summary)) {
    konteks += `- ${kategori}: Total ${data.total.toFixed(2)}, ${data.count} entri\n`;
  }
 
  return konteks;
}
  

Modul 2: Integrator ChatGPT API

Rumus/Function: callChatGPT(konteks)
function callChatGPT(konteks) {
  const configSheet = SpreadsheetApp.getActiveSpreadsheet()
                        .getSheetByName("Config");
  
  // Ambil API Key dan parameter dari tab Config
  // Asumsi: baris 2 kolom B = API Key, baris 3 kolom B = System Prompt
  const apiKey = configSheet.getRange("B2").getValue();
  const systemPrompt = configSheet.getRange("B3").getValue();
 
  const url = "https://api.openai.com/v1/chat/completions";
 
  const payload = {
    model: "gpt-4o",
    messages: [
      {
        role: "system",
        content: systemPrompt || "Kamu adalah analis bisnis. Buat ringkasan laporan mingguan yang jelas, singkat, dan actionable berdasarkan data yang diberikan."
      },
      {
        role: "user",
        content: konteks
      }
    ],
    max_tokens: 800,
    temperature: 0.4
  };
 
  const options = {
    method: "post",
    contentType: "application/json",
    headers: { "Authorization": "Bearer " + apiKey },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  };
 
  try {
    const response = UrlFetchApp.fetch(url, options);
    const result = JSON.parse(response.getContentText());
    
    if (result.error) {
      throw new Error("OpenAI Error: " + result.error.message);
    }
    
    return result.choices[0].message.content;
 
  } catch (e) {
    writeLog("ERROR", "callChatGPT gagal: " + e.message);
    throw e;
  }
}
  

Modul 3: Orchestrator dan Logger

Rumus/Function: runWeeklyReport() + writeLog()
function runWeeklyReport() {
  writeLog("START", "Pipeline otomasi laporan mingguan dimulai");
 
  try {
    // Step 1: Agregasi data
    const konteks = aggregateData();
    writeLog("OK", "Data berhasil diagregasi");
 
    // Step 2: Generate narasi via ChatGPT
    const narasi = callChatGPT(konteks);
    writeLog("OK", "Narasi berhasil dibuat oleh ChatGPT");
 
    // Step 3: Tulis hasil ke tab Laporan
    const laporanSheet = SpreadsheetApp.getActiveSpreadsheet()
                           .getSheetByName("Laporan");
    const timestamp = Utilities.formatDate(new Date(), "Asia/Jakarta", "yyyy-MM-dd HH:mm");
    laporanSheet.appendRow([timestamp, narasi]);
    writeLog("OK", "Laporan berhasil disimpan ke sheet");
 
    // Step 4: Kirim email ke penerima di Config
    const emailPenerima = SpreadsheetApp.getActiveSpreadsheet()
                            .getSheetByName("Config").getRange("B4").getValue();
    GmailApp.sendEmail(
      emailPenerima,
      "Laporan Mingguan Otomatis — " + timestamp,
      narasi
    );
    writeLog("OK", "Email berhasil dikirim ke " + emailPenerima);
 
  } catch (e) {
    writeLog("FATAL", "Pipeline gagal: " + e.message);
  }
}
 
function writeLog(status, pesan) {
  const logSheet = SpreadsheetApp.getActiveSpreadsheet()
                     .getSheetByName("System Log");
  const timestamp = Utilities.formatDate(new Date(), "Asia/Jakarta", "yyyy-MM-dd HH:mm:ss");
  logSheet.appendRow([timestamp, status, pesan]);
}
  

Langkah 3 — Konfigurasi Tab Config

Tab Config adalah jantung dari fleksibilitas sistem ini. Isi setiap baris sesuai kebutuhan tanpa harus membuka editor kode sama sekali.

Cell Label (Kolom A) Nilai (Kolom B)
A2 OpenAI API Key sk-proj-xxxxxxxxxxxxxxxxxxxx
A3 System Prompt Kamu adalah analis bisnis senior. Buat laporan mingguan yang ringkas dan actionable.
A4 Email Penerima tim-ops@perusahaan.com
A5 Nama Tim Operations Team

Satu catatan penting soal keamanan: untuk environment produksi, pertimbangkan menggunakan PropertiesService milik Apps Script alih-alih menyimpan API Key langsung di cell. Ini mencegah key terbaca oleh siapapun yang mendapat akses view ke spreadsheet.

Langkah 4 — Pasang Time-driven Trigger

Trigger adalah komponen yang membuat seluruh sistem berjalan tanpa intervensi manual. Langkah pemasangannya sangat sederhana:

  1. Di editor Apps Script, klik ikon jam (Triggers) di sidebar kiri
  2. Klik Add Trigger di pojok kanan bawah
  3. Pilih fungsi: runWeeklyReport
  4. Pilih event source: Time-driven
  5. Pilih tipe: Week timer
  6. Pilih hari: Every Monday
  7. Pilih waktu: 7am to 8am
  8. Klik Save

Setelah trigger aktif, Google akan meminta izin akses ke Gmail dan Sheets. Berikan izin menggunakan akun Google Workspace yang digunakan tim. Sejak saat itu, sistem berjalan mandiri setiap Senin pagi.

Langkah 5 — Validasi Sebelum Go-Live

Jangan langsung percaya bahwa sistem berjalan sempurna tanpa pengujian. Gunakan checklist validasi berikut sebelum mengaktifkan trigger mingguan:

  • Jalankan runWeeklyReport() secara manual dari editor — pastikan tidak ada error di execution log
  • Cek tab System Log — semua baris harus berstatus OK
  • Cek tab Laporan — narasi ChatGPT harus muncul dengan timestamp yang benar
  • Cek inbox email penerima — email harus masuk dalam hitungan menit
  • Coba kondisi error: kosongkan API Key sementara, jalankan ulang — pastikan log mencatat status FATAL dan sistem tidak crash tanpa pesan

Tips Lanjutan untuk Skala Lebih Besar

Setelah sistem dasar berjalan stabil, berikut beberapa ekstensi yang bisa ditambahkan sesuai kebutuhan tim:

Prompt Engineering yang Lebih Kontekstual

Masukkan perbandingan minggu-ke-minggu dalam konteks yang dikirim ke ChatGPT. Alih-alih hanya data minggu ini, sertakan juga data minggu lalu sehingga model dapat mengidentifikasi tren kenaikan atau penurunan secara otomatis.

Multi-recipient dengan Format Berbeda

Buat beberapa baris di tab Config untuk berbeda level audience: ringkasan eksekutif 3 paragraf untuk C-level, laporan detail per kategori untuk tim operasional. Panggil callChatGPT() dua kali dengan system prompt berbeda.

Conditional Alert

Tambahkan logika di aggregateData() untuk mendeteksi nilai yang melampaui threshold tertentu. Jika ada anomali, kirim Slack notification via webhook sebelum laporan mingguan reguler dikirim.

Pelajari Lebih Lanjut dan Mulai Implementasi

Framework yang kamu baca di atas bukan teori—ini adalah cetak biru yang bisa langsung diimplementasikan hari ini juga. Mulai dari struktur terkecil: buat spreadsheet dengan empat tab, salin fungsi runWeeklyReport(), dan jalankan secara manual. Lihat sendiri bagaimana data tim kamu berubah menjadi narasi yang bisa langsung dibaca manajemen.

Jika kamu ingin mendalami lebih lanjut tentang integrasi Apps Script dengan layanan eksternal lainnya—mulai dari Notion API, Slack webhook, hingga BigQuery—atau ingin mempelajari cara membangun prompt yang menghasilkan output lebih konsisten dan terstruktur, jelajahi artikel-artikel lain di blog ini. Setiap sistem otomasi yang solid selalu dimulai dari satu langkah sederhana: memahami framework sebelum menulis kode.

Tidak ada komentar:

Posting Komentar

Bottom Ad [Post Page]