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