Guides / SaaS
Email open rates and click rates tell you which messages land. Logging them to LogIt lets you:
// app/api/webhooks/resend/route.ts
import { logit } from "@/lib/logit";
interface ResendWebhookEvent {
type: string;
data: {
email_id: string;
from: string;
to: string[];
subject?: string;
click?: { link: string };
bounce?: { message: string };
};
}
export async function POST(req: Request) {
const payload = await req.json() as ResendWebhookEvent;
const to = payload.data.to[0] ?? "unknown";
const subject = payload.data.subject ?? "unknown";
switch (payload.type) {
case "email.opened":
await logit.now("emails", {
event: "Email opened",
description: `${to} opened: ${subject}`,
icon: "๐ง",
notify: false,
tags: { type: "open" },
metadata: { emailId: payload.data.email_id, to, subject },
});
break;
case "email.clicked":
await logit.now("emails", {
event: "Email link clicked",
description: `${to} clicked: ${payload.data.click?.link ?? "unknown"}`,
icon: "๐ฑ๏ธ",
notify: false,
tags: { type: "click" },
metadata: { to, link: payload.data.click?.link, subject },
});
break;
case "email.bounced":
await logit.now("emails", {
event: "Email bounced",
description: `${to}: ${payload.data.bounce?.message ?? "hard bounce"}`,
icon: "โ ๏ธ",
notify: true,
tags: { type: "bounce" },
metadata: { emailId: payload.data.email_id, to, subject },
});
break;
}
return new Response("ok");
}
// app/api/webhooks/sendgrid/route.ts
interface SendGridEvent {
event: string;
email: string;
subject?: string;
url?: string;
timestamp: number;
}
export async function POST(req: Request) {
const events = await req.json() as SendGridEvent[];
for (const ev of events) {
if (ev.event === "open" || ev.event === "click") {
await logit.now("emails", {
event: `Email ${ev.event}`,
description: ev.email,
icon: ev.event === "open" ? "๐ง" : "๐ฑ๏ธ",
notify: false,
tags: { provider: "sendgrid", type: ev.event },
metadata: { email: ev.email, subject: ev.subject, timestamp: ev.timestamp },
});
}
}
return new Response("ok");
}
Try LogIt free
7-day trial. No credit card required.