Email Deliverability Best Practices dengan Resend di Helipod
이 글은 인도네시아어로 작성되었습니다.
Email terkirim tapi masuk spam? Atau bahkan ga sampai sama sekali? Masalah email deliverability adalah mimpi buruk bagi developer.
Artikel ini solusinya.
Apa Itu Email Deliverability?#
Email deliverability adalah kemampuan email kamu untuk sampai ke inbox penerima, bukan ke spam folder.
Email terkirim ≠ Email sampai ke inbox
Email terkirim → Processing → Filtering → Inbox/Spam
↑ ↑
Authentication Reputation
Faktor yang Mempengaruhi#
| Faktor | Pengaruh |
|---|---|
| Domain authentication | ⭐⭐⭐⭐⭐ |
| IP reputation | ⭐⭐⭐⭐ |
| Content quality | ⭐⭐⭐ |
| Sending frequency | ⭐⭐⭐ |
| Bounce rate | ⭐⭐⭐⭐ |
1. Setup Domain Authentication#
SPF (Sender Policy Framework)#
SPF memverifikasi bahwa email dikirim dari server yang diizinkan.
DNS Record:
Type: TXT
Name: @
Value: v=spf1 include:sendgrid.net ~all
DKIM (DomainKeys Identified Mail)#
DKIM menandatangani email secara kriptografis untuk memverifikasi bahwa email belum diubah.
DNS Record:
Type: TXT
Name: resend._domainkey
Value: v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA...
DMARC (Domain-based Message Authentication)#
DMARC memberitahu receiver apa yang harus dilakukan jika email gagal verifikasi.
DNS Record:
Type: TXT
Name: _dmarc
Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@helipod.io
Setup di Resend#
- Buka Resend Dashboard → Domains
- Tambahkan domain kamu
- Copy DNS records yang diberikan
- Tambahkan ke DNS provider kamu
- Tunggu verifikasi (5-15 menit)
2. Warm Up Domain#
Kenapa Perlu Warm Up?#
Domain baru → Langsung kirim 1000 email → Spam!
Domain baru → Gradually increase → Inbox
Schedule Warm Up#
Minggu 1: 10-20 email/hari
Minggu 2: 30-50 email/hari
Minggu 3: 100-200 email/hari
Minggu 4: 300-500 email/hari
Minggu 5: 500-1000 email/hari
Implementasi#
// Warm up scheduler
const WARM_UP_SCHEDULE = [
{ week: 1, dailyLimit: 20 },
{ week: 2, dailyLimit: 50 },
{ week: 3, dailyLimit: 200 },
{ week: 4, dailyLimit: 500 },
{ week: 5, dailyLimit: 1000 },
];
async function sendWithWarmUp(email) {
const domainAge = getDomainAge(email.from);
const schedule = WARM_UP_SCHEDULE.find(s =>
domainAge >= (s.week - 1) * 7 && domainAge < s.week * 7
);
const sentToday = await getSentCountToday(email.from);
if (sentToday >= schedule.dailyLimit) {
throw new Error('Daily limit reached');
}
return await resend.emails.send(email);
}
3. Content Best Practices#
Subject Line#
# ❌ Hindari
"FREE!!! Click here now!!!"
"URGENT: Your account will be closed"
"Buy now, limited time offer"
# ✅ Gunakan
"Your invoice from Helipod"
"Welcome to Helipod"
"Password reset request"
Email Body#
<!-- ❌ Hindari -->
<html>
<body>
<h1 style="color: red; font-size: 24px;">BELI SEKARANG!!!</h1>
<p>Klik di sini untuk mendapatkan DISKON 90%!!!</p>
<a href="http://bit.ly/xxx">KLIK DI SINI</a>
</body>
</html>
<!-- ✅ Gunakan -->
<html>
<body style="font-family: Arial, sans-serif; color: #333;">
<h1>Selamat datang di Helipod!</h1>
<p>Halo Budi,</p>
<p>Akun kamu sudah aktif. Mulai deploy aplikasi sekarang.</p>
<a href="https://helipod.io/dashboard"
style="background: #10b981; color: white; padding: 10px 20px; text-decoration: none;">
Dashboard
</a>
</body>
</html>
Tips Content#
- Personalisasi: Gunakan nama penerima
- Relevansi: Pastikan konten relevan dengan penerima
- CTA jelas: Satu action yang jelas
- Unsubscribe link: Selalu sertakan
- Balance text/image: Minimal 60% text, 40% image
4. List Management#
Bersihkan Email List#
// Hapus email bounce
async function cleanBouncedEmails() {
const emails = await resend.emails.list();
for (const email of emails) {
if (email.last_event === 'bounced') {
await removeFromList(email.to);
console.log(`Removed bounced: ${email.to}`);
}
}
}
Validasi Email#
// Validasi sebelum kirim
function validateEmail(email) {
// Cek format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) return false;
// Cek disposable email
const disposableDomains = ['tempmail.com', 'throwaway.email'];
const domain = email.split('@')[1];
if (disposableDomains.includes(domain)) return false;
return true;
}
Double Opt-in#
// Double opt-in untuk newsletter
async function subscribe(email) {
// 1. Kirim email konfirmasi
await resend.emails.send({
from: 'noreply@helipod.io',
to: email,
subject: 'Konfirmasi subscription',
html: `
<p>Klik link untuk konfirmasi:</p>
<a href="https://helipod.io/confirm?token=${token}">
Konfirmasi
</a>
`
});
// 2. Tunggu konfirmasi
// 3. Tambahkan ke list setelah konfirmasi
}
5. Monitoring Deliverability#
Metrics yang Perlu Dipantau#
1. Delivery Rate
- Target: > 95%
- Alert: < 90%
2. Bounce Rate
- Target: < 2%
- Alert: > 5%
3. Open Rate
- Target: > 20%
- Alert: < 10%
4. Spam Complaint Rate
- Target: < 0.1%
- Alert: > 0.3%
Dashboard Monitoring#
Di Helipod, kamu bisa monitor:
Email Analytics:
├── Total sent: 12,345
├── Delivered: 12,100 (98%)
├── Opened: 4,500 (37%)
├── Clicked: 1,200 (10%)
├── Bounced: 145 (1.2%)
└── Complaints: 5 (0.04%)
Alert Setup#
// Alert jika bounce rate tinggi
async function checkDeliverability() {
const stats = await resend.analytics.get();
const bounceRate = stats.bounced / stats.sent;
const complaintRate = stats.complaints / stats.sent;
if (bounceRate > 0.05) {
await sendAlert(`High bounce rate: ${(bounceRate * 100).toFixed(1)}%`);
}
if (complaintRate > 0.003) {
await sendAlert(`High complaint rate: ${(complaintRate * 100).toFixed(2)}%`);
}
}
6. Handling Bounce dan Complaint#
Bounce Handling#
// Jangan kirim ke email yang bounce
async function shouldSend(email) {
const history = await getSendHistory(email);
// Hard bounce = jangan kirim lagi
if (history.hardBounces > 0) {
return false;
}
// Soft bounce = coba lagi nanti
if (history.softBounces > 3) {
return false;
}
return true;
}
Complaint Handling#
// Jika user complain, jangan kirim lagi
async function handleComplaint(email) {
await removeFromAllLists(email);
await addToSuppressionList(email);
console.log(`Complaint from ${email} - suppressed`);
}
7. Advanced Techniques#
Segmentation#
// Kirim berdasarkan segment
const segments = {
active: users.filter(u => u.lastLogin > daysAgo(30)),
inactive: users.filter(u => u.lastLogin <= daysAgo(30)),
trial: users.filter(u => u.plan === 'trial'),
};
Personalisasi Lanjut#
// Personalisasi berdasarkan behavior
async function sendPersonalizedEmail(user) {
const recommendations = await getRecommendations(user.id);
await resend.emails.send({
to: user.email,
subject: `Rekomendasi untuk ${user.name}`,
html: `
<h1>Halo ${user.name}!</h1>
<p>Berdasarkan aktivitas kamu, kami rekomendasikan:</p>
<ul>
${recommendations.map(r => `<li>${r.name}</li>`).join('')}
</ul>
`
});
}
A/B Testing#
// A/B testing subject line
async function abTest(users) {
const half = Math.floor(users.length / 2);
// Group A
await sendBatch(users.slice(0, half), {
subject: 'Selamat datang di Helipod!'
});
// Group B
await sendBatch(users.slice(half), {
subject: 'Akun kamu sudah aktif!'
});
// Compare open rates
}
Checklist Deliverability#
- Domain authentication (SPF, DKIM, DMARC)
- Warm up schedule
- Content best practices
- List cleaning
- Email validation
- Double opt-in
- Monitoring setup
- Bounce handling
- Complaint handling
Kesimpulan#
Email deliverability adalah kunci keberhasilan email marketing. Dengan best practices di atas, kamu bisa:
- ✅ Email masuk inbox, bukan spam
- ✅ Meningkatkan open rate
- ✅ Mengurangi bounce rate
- ✅ Menjaga reputasi domain
Butuh bantuan? Hubungi support@helipod.io
Baca juga: