Aggregate email metrics hide which campaign is hurting your sender reputation. A bounce rate of 4% looks alarming in aggregate but harmless if it comes entirely from one poorly-segmented cold campaign — and fixable once you can isolate it. Without campaign_id on individual event records, triage requires reconstructing send state from logs and timestamps, which takes hours during an active incident. The Campaign Analytics & Attribution Audit validates attribution accuracy; this check verifies that the raw event storage layer records the campaign context in the first place.
Medium because missing campaign attribution makes deliverability triage time-consuming and imprecise, slowing incident response during bounce rate spikes.
Include campaign_id on every email event record in your webhook handler (e.g., src/app/api/webhooks/email/route.ts):
await db.emailEvent.create({
data: {
type: 'bounce',
campaign_id: send.campaignId,
contact_id: send.contactId,
recorded_at: new Date()
}
})
All five event types — bounce, complaint, open, click, and unsubscribe — must include campaign attribution at the individual event level. Aggregate-only storage does not satisfy this check.
ID: operational-resilience-email.monitoring-alerting.per-campaign-health-tracked
Severity: medium
What to look for: Enumerate all email event recording locations (bounce handler, complaint handler, open tracker, click tracker, unsubscribe handler). For each, check whether a campaign_id or equivalent foreign key is included in the event record. Count the number of event types that include campaign attribution versus total event types. Report: X of Y event types include campaign_id.
Pass criteria: At least 4 of 5 email event types (bounce, complaint, open, click, unsubscribe) include a campaign identifier in the event record that allows filtering and aggregation per campaign. Do NOT pass when events are recorded in aggregate only — campaign attribution must be present at the individual event level.
Fail criteria: Events are recorded in aggregate only with no campaign attribution — you cannot tell which campaign is causing a deliverability problem without manual investigation. Or fewer than 4 of 5 event types include a campaign_id.
Skip (N/A) when: The system sends only transactional emails with no campaign concept — confirmed by the absence of campaign models, campaign tables, or campaign-related code.
Detail on fail: "Email events are stored without campaign attribution — bounce rates cannot be segmented by campaign" or "Metrics are emitted without campaign_id tag — all sends appear as one aggregate pool"
Cross-reference: The Campaign Analytics & Attribution Audit verifies that attribution data is accurate and complete — this check verifies that the event recording layer includes the campaign context needed for per-campaign health segmentation.
Remediation: Include campaign ID in all event records in your webhook handler (e.g., src/app/api/webhooks/email/route.ts):
await db.emailEvent.create({
data: {
type: 'bounce',
campaign_id: send.campaignId,
contact_id: send.contactId,
recorded_at: new Date()
}
})