Metrics and analytics
Email Service exposes analytics that allow you to inspect email sending performance and delivery rates across all your domains.
The metrics displayed in the Cloudflare dashboard ↗ charts are queried from Cloudflare's GraphQL Analytics API. You can access the metrics programmatically via GraphQL or HTTP client.
Email Service currently exposes the below metrics:
| Dataset | GraphQL Dataset Name | Description |
|---|---|---|
| Sending (aggregated) | emailSendingAdaptiveGroups | Aggregated email sending counts grouped by dimensions such as status, date, sending domain, and authentication results. |
| Sending (events) | emailSendingAdaptive | Individual email sending events with full detail including sender, recipient, subject, message ID, and error information. |
Metrics can be queried (and are retained) for the past 31 days.
Per-domain analytics for Email Service are available in the Cloudflare dashboard. To view current and historical metrics:
- Log in to the Cloudflare dashboard ↗ and select your account.
- Go to Compute > Email Service ↗.
- Select an existing domain or view account-wide metrics.
- Select the Analytics tab.
You can optionally select a time window to query. This defaults to the last 24 hours.
You can programmatically query analytics for your Email Service domains via the GraphQL Analytics API. This API queries the same datasets as the Cloudflare dashboard, and supports GraphQL introspection.
To get started using the GraphQL Analytics API, follow the documentation to setup Authentication for the GraphQL Analytics API. Your API token must include the Analytics Read permission.
These are zone-level datasets. To query them, provide your zone ID (not account ID) as the zoneTag filter. The GraphQL datasets for Email Service include:
emailSendingAdaptiveGroups— aggregated counts with groupable dimensionsemailSendingAdaptive— individual email events
The emailSendingAdaptiveGroups dataset supports the following dimensions for grouping and filtering:
| Dimension | Type | Description |
|---|---|---|
date | Date | Day-level grouping |
datetime | Time | Exact event timestamp |
datetimeMinute | Time | Minute-level grouping |
datetimeFiveMinutes | Time | 5-minute interval grouping |
datetimeFifteenMinutes | Time | 15-minute interval grouping |
datetimeHour | Time | Hour-level grouping |
status | string | Delivery status (for example, delivered, deliveryFailed) |
eventType | string | Type of sending event |
sendingDomain | string | The domain used to send the email |
envelopeTo | string | Recipient envelope address |
errorCause | string | Error cause for failed sends |
arc | string | ARC authentication result |
dkim | string | DKIM authentication result |
dmarc | string | DMARC authentication result |
spf | string | SPF authentication result |
isSpam | uint8 | Whether the email was flagged as spam |
isNDR | uint8 | Whether the email is a non-delivery report |
The emailSendingAdaptive dataset includes all of the above plus per-event fields: from, to, subject, messageId, sessionId, errorDetail.
The following are common GraphQL queries that you can use to retrieve information about Email Service analytics. These queries use the variable $zoneTag, which should be set to your Cloudflare Zone ID. You can find this in the Cloudflare dashboard under your domain's Overview page.
{ "zoneTag": "<YOUR_ZONE_ID>", "start": "2024-07-15", "end": "2024-07-30"}To query the count of emails for a given date range, grouped by date and status (for example, delivered, deliveryFailed):
query EmailSendingByStatus($zoneTag: string!, $start: Date!, $end: Date!) { viewer { zones(filter: { zoneTag: $zoneTag }) { emailSendingAdaptiveGroups( filter: { date_geq: $start, date_leq: $end } limit: 10000 orderBy: [date_DESC] ) { count dimensions { date status } } } }}To investigate delivery failure causes for a specific date range, grouped by errorCause and sendingDomain:
query EmailDeliveryFailures($zoneTag: string!, $start: Date!, $end: Date!) { viewer { zones(filter: { zoneTag: $zoneTag }) { emailSendingAdaptiveGroups( filter: { date_geq: $start, date_leq: $end, status: "deliveryFailed" } limit: 10000 orderBy: [date_DESC] ) { count dimensions { date errorCause sendingDomain } } } }}To query email sending volume grouped by hour, useful for identifying traffic patterns:
query EmailSendingHourlyVolume($zoneTag: string!, $start: Time!, $end: Time!) { viewer { zones(filter: { zoneTag: $zoneTag }) { emailSendingAdaptiveGroups( filter: { datetimeHour_geq: $start, datetimeHour_leq: $end } limit: 10000 orderBy: [datetimeHour_ASC] ) { count dimensions { datetimeHour status } } } }}To query individual email events for troubleshooting specific delivery issues. This uses the emailSendingAdaptive dataset and filters by datetime (Time type):
query RecentEmailEvents($zoneTag: string!, $start: Time!, $end: Time!) { viewer { zones(filter: { zoneTag: $zoneTag }) { emailSendingAdaptive( filter: { datetime_geq: $start, datetime_leq: $end } limit: 50 orderBy: [datetime_DESC] ) { datetime from to subject status eventType sendingDomain messageId errorCause errorDetail dkim dmarc spf isSpam } } }}