Analytics aggregation

Mailgun webhook /api/email/webhooks/mailgun (already exists) currently handles delivered/bounce. Extend to consume: opened, clicked, complained, unsubscribed.

For each event:

  1. Look up Campaign.mailgunId (stored at send time).

  2. Resolve CampaignLog by (campaignId, subscriberId) — Mailgun event payload includes recipient + message-id -> tag mapping.

  3. Set the matching boolean + timestamp column on CampaignLog.

  4. Recompute the per-campaign rollups on Campaign (opened, clicked, bounced, ...) using:

    const rollup = await prisma.campaignLog.groupBy({
      by: ['campaignId'],
      where: { campaignId },
      _count: { opened: true, clicked: true, bounced: true, delivered: true, unsubscribed: true, complained: true },
    })
    await prisma.campaign.update({ where: { id: campaignId }, data: {
      opened: rollup[0]._count.opened, clicked: rollup[0]._count.clicked, bounced: rollup[0]._count.bounced,
      delivered: rollup[0]._count.delivered, unsubscribed: rollup[0]._count.unsubscribed, complained: rollup[0]._count.complained,
    }})
    
  5. Subscribe to Mailgun event types: delivered, opened, clicked, bounced, complained, unsubscribed (via dashboard or POST /v3/domains/{domain}/webhooks/{hookid}).

Engagement rollups on Subscriber (emailsOpened, linksClicked, lastOpenedAt, lastClickedAt) can be updated in the same handler keyed off subscriberId.

Choose Theme

Your selection is saved locally.

Neural Cacophony
Aperture v2
Flux v1
Mosaic Chaos
Nexus v1
Nexus Zest
Prism v2
Synapse