Tambahkan Notifikasi Email ke Situs Booking AI Anda
Kirim email konfirmasi booking dan peringatan pemilik menggunakan Supabase, Resend, dan Edge Functions.
Roadmap & sumber daya
Baru di sini? Mulai dari sini dulu
Panduan ini meningkatkan proyek Situs Booking AI dengan notifikasi email otomatis. Jika Anda belum membangun situs booking, mulai dengan panduan utama terlebih dahulu.
Bangun Situs Booking dengan AI
Buka panduan utama
MAIN GUIDE
https://profitstudio.app/video/build-booking-website-ai
Siapkan Resend untuk Email Booking
Buat dan Konfigurasikan Akun Resend Anda
Buka Resend
https://resend.com/
Buat akun Resend Buat API key Resend Salin dan simpan API key dengan aman
PENTING
Jaga kerahasiaan API key Resend. Jangan pernah menambahkannya ke kode frontend atau membagikannya secara publik.
Tambahkan dan Verifikasi Domain Pengirim
Tambahkan domain situs booking Anda Pilih region terdekat Salin data DNS dari Resend Tambahkan data tersebut di penyedia domain Anda Kembali ke Resend dan pastikan domain sudah terverifikasi
Verifikasi DNS bisa memakan waktu beberapa menit atau lebih, tergantung penyedia domain Anda.
Buat Fungsi Email Booking
Buat Edge Function Email Booking
Buka Supabase
https://supabase.com/?utm_source=partner&utm_medium=social&utm_campaign=supasquad&dub_id=faVfKdcLWvKCbYNp
Buka proyek Supabase Anda Buka Edge Functions Buat function baru menggunakan editor di browser Beri nama function `send-booking-email` Hapus kode awal bawaan
Sesuaikan dan Tambahkan Kode Function
Masukkan email pemilik Masukkan domain Resend yang sudah terverifikasi Masukkan nama bisnis pengirim Sesuaikan template email jika diperlukan Salin dan tempel kode function yang dihasilkan
Fungsi Email Booking
import { serve } from "https://deno.land/std/http/server.ts"; serve(async (req) => { try { const body = await req.json(); const record = body.record || {}; const resendKey = Deno.env.get("RESEND_API_KEY"); const supabaseUrl = Deno.env.get("SUPABASE_URL"); const supabaseServiceRoleKey = Deno.env.get("SUPABASE_SERVICE_ROLE_KEY"); if (!resendKey) { return new Response( JSON.stringify({ error: "Missing RESEND_API_KEY secret" }), { status: 500, headers: { "Content-Type": "application/json" }, } ); } const ownerEmail = "YOUR_OWNER_EMAIL"; const customerEmail = record.email || ""; const customerName = record.full_name || record.name || "Customer"; const phone = record.phone || ""; const appointmentDate = record.appointment_date || record.date || ""; const startTime = record.start_time || record.time || ""; const endTime = record.end_time || ""; const notes = record.notes || ""; const status = record.status || "New"; let serviceName = record.service_name || record.service || record.service_title || ""; // If the appointment only has service_id, fetch the service name from the services table if (!serviceName && record.service_id && supabaseUrl && supabaseServiceRoleKey) { try { const serviceId = encodeURIComponent(record.service_id); const serviceResponse = await fetch( `${supabaseUrl}/rest/v1/services?id=eq.${serviceId}&select=name`, { method: "GET", headers: { apikey: supabaseServiceRoleKey, Authorization: `Bearer ${supabaseServiceRoleKey}`, "Content-Type": "application/json", }, } ); const serviceData = await serviceResponse.json(); if (Array.isArray(serviceData) && serviceData.length > 0) { serviceName = serviceData[0].name || ""; } } catch (_serviceError) { serviceName = ""; } } if (!serviceName) { serviceName = "Appointment"; } // 1) Email to business owner const ownerResponse = await fetch("https://api.resend.com/emails", { method: "POST", headers: { Authorization: `Bearer ${resendKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "Bookings <bookings@YOUR_DOMAIN_NAME>", to: [ownerEmail], subject: "OWNER_NOTIFICATION_SUBJECT", html: ` <h2>OWNER_NOTIFICATION_HEADING</h2> <p>OWNER_NOTIFICATION_INTRO</p> <p><b>Customer Name:</b> ${customerName}</p> <p><b>Email:</b> ${customerEmail}</p> <p><b>Phone:</b> ${phone}</p> <p><b>Service:</b> ${serviceName}</p> <p><b>Date:</b> ${appointmentDate}</p> <p><b>Start Time:</b> ${startTime}</p> <p><b>End Time:</b> ${endTime}</p> <p><b>Notes:</b> ${notes}</p> <p><b>Status:</b> ${status}</p> `, }), }); const ownerData = await ownerResponse.json(); // 2) Email to customer let customerData = null; if (customerEmail) { const customerResponse = await fetch("https://api.resend.com/emails", { method: "POST", headers: { Authorization: `Bearer ${resendKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: "YOUR_BUSINESS_NAME <bookings@YOUR_DOMAIN_NAME>", to: [customerEmail], subject: "CUSTOMER_CONFIRMATION_SUBJECT", html: ` <h2>CUSTOMER_CONFIRMATION_HEADING</h2> <p>Hi ${customerName},</p> <p>CUSTOMER_CONFIRMATION_INTRO</p> <p><b>Service:</b> ${serviceName}</p> <p><b>Date:</b> ${appointmentDate}</p> <p><b>Start Time:</b> ${startTime}</p> <p><b>End Time:</b> ${endTime}</p> <p>If you need to make any changes, please contact us before your appointment.</p> <p>CUSTOMER_CONFIRMATION_CLOSING</p> `, }), }); customerData = await customerResponse.json(); } return new Response( JSON.stringify({ success: true, ownerEmailSent: ownerData, customerEmailSent: customerData, }), { headers: { "Content-Type": "application/json" }, } ); } catch (error) { return new Response( JSON.stringify({ success: false, error: String(error), }), { status: 500, headers: { "Content-Type": "application/json" }, } ); } });
Email pemilik
owner@example.com
Domain Resend Terverifikasi
yourdomain.com
Nama bisnis pengirim
Klinik Gigi Bright
Subjek email pemilik
Heading email pemilik
Teks pembuka email pemilik
Subjek email pelanggan
Heading email pelanggan
Teks pembuka email pelanggan
Teks penutup email pelanggan
Deploy dan Konfigurasikan Function
Deploy function tersebut Buka pengaturan function Nonaktifkan `Verify JWT With Legacy Secret` Simpan perubahan Salin dan simpan URL endpoint function untuk pengaturan webhook
PENTING
Nonaktifkan “Verify JWT With Legacy Secret” agar Database Webhook dapat memanggil function tersebut.
Tambahkan API Key Resend ke Supabase
Tambahkan API Key Resend sebagai Secret Supabase
Buka Edge Function Secrets Buat secret baru Atur namanya menjadi `RESEND_API_KEY` Tempel API key Resend Simpan secret tersebut
PENTING
Gunakan nama secret persis `RESEND_API_KEY`. Salah ketik sedikit saja akan membuat function tidak bisa mengakses Resend.
Hubungkan Email ke Booking Baru
Buat Webhook Email Booking
Jalankan function email booking setiap kali ada janji temu baru ditambahkan.
Integrations Database Webhooks
Buka Database Webhooks Aktifkan Database Webhooks Buat webhook baru Beri nama `send-booking-email-webhook` Pilih tabel `public.appointments` Pilih `Insert` sebagai event Biarkan tipenya tetap `HTTP Request` Gunakan `POST` sebagai metode request Tempel URL endpoint Edge Function Buat webhook tersebut
Uji Sistem Email Booking
Uji Alur Email Booking Secara Lengkap
Uji alur booking secara lengkap dan pastikan kedua email terkirim dengan benar.
Buka situs booking versi live Kirim janji temu uji coba Pastikan booking tersimpan di Supabase Periksa email konfirmasi untuk pelanggan Periksa email notifikasi untuk pemilik Pastikan detail booking benar di kedua email Pastikan booking muncul di dashboard admin