Kategori: Programming | Perkiraan waktu baca: 10 menit
Salah satu proyek SaaS lain yang saya bangun dengan stack yang sama seperti ARES — Next.js dan Supabase — adalah aplikasi auto-scheduler Instagram, yang memungkinkan user menjadwalkan post Instagram dari jauh hari dan otomatis ke-publish tanpa perlu buka aplikasi Instagram di jam yang ditentukan.
Di artikel ini saya bahas arsitekturnya, terutama bagian yang paling menantang: integrasi dengan Meta Graph API dan sistem antrian (queue) untuk publish terjadwal.
Kenapa Butuh Auto-Scheduler?
Buat bisnis atau content creator yang posting rutin, menjadwalkan konten di muka itu jauh lebih efisien dibanding harus manual posting tiap hari di jam tertentu — apalagi kalau target audiens ada di jam-jam yang kurang nyaman (misal tengah malam karena beda zona waktu).
Kenapa Meta Graph API, Bukan Automasi Browser?
Ada dua pendekatan untuk auto-posting Instagram: automasi browser (mirip pendekatan whatsapp-web.js yang saya bahas di artikel WhatsApp Bot) atau pakai API resmi dari Meta. Saya pilih Meta Graph API resmi karena:
- Lebih stabil — nggak gampang rusak setiap kali Meta ubah tampilan web mereka
- Lebih aman — nggak melanggar Terms of Service Instagram seperti automasi browser
- Mendukung Instagram Business/Creator account dengan fitur resmi seperti insight dan analytics
Konsekuensinya, user harus punya akun Instagram Business/Creator yang terhubung ke Facebook Page, karena Graph API cuma bisa akses akun jenis itu, bukan akun personal biasa.
Alur Autentikasi (OAuth)
Langkah pertama, user perlu authorize aplikasi kita untuk akses akun Instagram Business mereka lewat Facebook Login:
// Redirect user ke halaman OAuth Facebook
const authUrl = `https://www.facebook.com/v19.0/dialog/oauth?` +
`client_id=${process.env.META_APP_ID}&` +
`redirect_uri=${encodeURIComponent(REDIRECT_URI)}&` +
`scope=instagram_basic,instagram_content_publish,pages_show_list`;
// Setelah user approve, Meta redirect balik dengan authorization code
// Tukar code itu dengan access token:
async function exchangeCodeForToken(code) {
const response = await fetch(
`https://graph.facebook.com/v19.0/oauth/access_token?` +
`client_id=${process.env.META_APP_ID}&` +
`client_secret=${process.env.META_APP_SECRET}&` +
`redirect_uri=${encodeURIComponent(REDIRECT_URI)}&` +
`code=${code}`
);
return response.json();
}
Setelah dapat access token, kita perlu cari ID akun Instagram Business yang terhubung ke Page Facebook user:
async function getInstagramBusinessAccountId(pageAccessToken, pageId) {
const response = await fetch(
`https://graph.facebook.com/v19.0/${pageId}?fields=instagram_business_account&access_token=${pageAccessToken}`
);
const data = await response.json();
return data.instagram_business_account?.id;
}
Menyimpan Jadwal Post ke Database
Struktur tabel di Supabase:
create table scheduled_posts (
id uuid default gen_random_uuid() primary key,
user_id uuid references auth.users(id) not null,
instagram_account_id text not null,
caption text,
media_url text not null,
scheduled_time timestamptz not null,
status text default 'pending', -- pending, published, failed
created_at timestamptz default now()
);
Sistem Antrian untuk Publish Terjadwal
Ini bagian paling penting — bagaimana memastikan post benar-benar ter-publish tepat waktu, meski server bisa saja restart atau ada ratusan post terjadwal sekaligus. Saya pakai BullMQ (berbasis Redis) untuk job queue:
const { Queue, Worker } = require('bullmq');
const publishQueue = new Queue('instagram-publish', {
connection: { host: 'localhost', port: 6379 }
});
// Menambahkan job baru saat user menjadwalkan post
async function schedulePost(postData) {
const delay = new Date(postData.scheduled_time).getTime() - Date.now();
await publishQueue.add('publish-post', postData, {
delay: Math.max(delay, 0),
attempts: 3,
backoff: { type: 'exponential', delay: 5000 },
});
}
// Worker yang benar-benar eksekusi publish
const worker = new Worker('instagram-publish', async (job) => {
const { instagram_account_id, caption, media_url, access_token } = job.data;
// Step 1: Buat media container
const containerRes = await fetch(
`https://graph.facebook.com/v19.0/${instagram_account_id}/media`,
{
method: 'POST',
body: new URLSearchParams({
image_url: media_url,
caption: caption,
access_token: access_token,
}),
}
);
const container = await containerRes.json();
// Step 2: Publish container yang sudah dibuat
const publishRes = await fetch(
`https://graph.facebook.com/v19.0/${instagram_account_id}/media_publish`,
{
method: 'POST',
body: new URLSearchParams({
creation_id: container.id,
access_token: access_token,
}),
}
);
return publishRes.json();
}, { connection: { host: 'localhost', port: 6379 } });
Publish ke Instagram lewat Graph API itu dua langkah — bukan langsung upload dan publish sekaligus: pertama bikin "container" media, baru kemudian publish container itu. Ini desain resmi dari Meta, bukan keputusan saya.
Menangani Token yang Expired
Access token dari Meta punya masa berlaku terbatas. Saya implementasikan refresh otomatis:
async function refreshLongLivedToken(shortLivedToken) {
const response = await fetch(
`https://graph.facebook.com/v19.0/oauth/access_token?` +
`grant_type=fb_exchange_token&` +
`client_id=${process.env.META_APP_ID}&` +
`client_secret=${process.env.META_APP_SECRET}&` +
`fb_exchange_token=${shortLivedToken}`
);
return response.json(); // Token ini berlaku sekitar 60 hari
}
Saya jadwalkan job terpisah yang jalan berkala untuk refresh token sebelum expired, supaya user nggak perlu re-authorize manual setiap beberapa minggu.
Tantangan yang Saya Hadapi
- Rate limiting dari Meta — API punya limit request per jam, jadi untuk user dengan banyak akun terjadwal, perlu strategi throttling di sisi aplikasi kita sendiri
- Approval aplikasi dari Meta — untuk fitur publish content di luar mode testing, aplikasi perlu melalui App Review dari Meta, prosesnya nggak instan
- Media harus accessible dari URL publik — Graph API butuh URL gambar yang bisa diakses publik, jadi perlu setup storage (saya pakai Supabase Storage) yang bisa serve gambar dengan URL publik
Penutup
Membangun scheduler Instagram ini banyak mengajarkan saya soal kompleksitas bekerja dengan API pihak ketiga yang official tapi tetap punya banyak "gotcha" — dari alur OAuth dua langkah publish, sampai app review process. Kalau kamu belum familiar dengan stack dasarnya, artikel Cara Deploy Next.js + Supabase bisa jadi titik awal yang baik.
Kalau kamu butuh bantuan membangun tools social media automation atau integrasi API pihak ketiga lainnya, saya buka jasa untuk itu. Cek portofolio saya di april-portfolio-pearl.vercel.app atau hubungi lewat halaman Contact.
Ada pertanyaan soal integrasi Meta API atau sistem queue-nya? Tulis di komentar.

Tidak ada komentar:
Posting Komentar