# Analytics dimensions

A dimension is a property of your email, such as the mailbox provider or the sending domain. You use dimensions in two ways:

- In `group_by`, a dimension splits a metric into one row per value. The result is a breakdown.
- In `filters`, a dimension limits the query to the values that you select.

To see the values that a dimension has in your data, group by that dimension.

## Traffic dimensions

These dimensions describe the email that you sent. They work with every metric.

| Dimension | Value |
| --- | --- |
| `project_id` | The ID of the project. A UUID. |
| `route_id` | The ID of the route. A UUID. |
| `message_type` | The type of the route: `transactional` or `broadcast`. |
| `sending_domain` | The domain that you sent from. |
| `recipient_domain` | The domain of the recipient address, such as `gmail.com`. |
| `provider_family` | The mailbox provider that receives the email, such as `Google` or `Microsoft`. One provider can serve many recipient domains. |
| `provider_subtype` | A part of the provider, when Lettermint can identify it. An example is the consumer service of a provider. |

`provider_family` and `provider_subtype` also [change what is counted](#dimensions-that-change-what-is-counted).

Use `provider_family` to answer most delivery questions. A company that hosts its email with Google has its own recipient domain, but the provider is still `Google`.

## Tags

Use `tag:` and the name of a [tag](/platform/emails/tags) as a dimension. For the tag `campaign`, the dimension is `tag:campaign`, and its values are the values that you sent, such as `welcome`. Tag names are case-sensitive.

Analytics use the name and value pairs from the `tags` field. The singular `tag` field is not a dimension.

| Rule | Detail |
| --- | --- |
| Tags per query | One. You can group by and filter on the same tag. |
| Other dimensions in the same query | `project_id`, `route_id`, `message_type`, `sending_domain`, and `provider_family` |
| Metrics | All metrics except opens, clicks, and their rates |
| Filter operators | All operators except `is_null` |

## From address and subject

`from_address` and `subject` hold personal data. They have more rules than other dimensions.

| Rule | Detail |
| --- | --- |
| Access | The token also needs `read:messages`. A team member also needs **View messages**. |
| MCP | Not available while personal-information filtering is on for the team. |
| Other dimensions in the same query | `project_id`, `route_id`, and `message_type` |
| Metrics | All metrics except opens, clicks, and their rates |
| Interval | `day` only |
| Time zone | Daily buckets for these dimensions are UTC days. Use `UTC` as the time zone to get exact daily buckets. |
| History | Lettermint deletes the from address and the subject when the retention period of the message ends. See [Data retention](/platform/emails/data-retention). |

## SMTP dimensions

These dimensions describe the answer of the receiving server. They have a value for temporary failures and bounces, so they explain why email was not delivered.

| Dimension | Value |
| --- | --- |
| `smtp_code` | The three-digit reply code, such as `550`. |
| `enhanced_status_code` | The enhanced status code, such as `5.1.1`. |
| `enhanced_status_category` | The first two parts of the enhanced status code, such as `5.1`. |
| `bounce_classification` | The cause that Lettermint assigned, such as `InvalidRecipient`, `SpamBlock`, or `QuotaIssues`. |
| `failure_reason` | A reason that Lettermint recorded for some failures, such as `enforced_tls_failed`. |
| `smtp_response_group` | The reply of the receiving server, with the reply code, the enhanced status code, and the text. An example is `550 5.1.1 Mailbox <email> does not exist`. |

SMTP dimensions support these metrics only: `delivered`, `bounced`, `soft_bounced`, `administratively_bounced`, `deferred_events`, `deferred_recipients`, `delivery_attempts`, `attempted_recipients`, `mta_accepted`, and `transport_outcome_recipients`. Rates are not available.

### SMTP response groups

Receiving servers put addresses, IP addresses, and session IDs in their replies. Two replies with the same meaning then have different text. Lettermint replaces these parts with placeholders such as `<email>` and `<ip>`, and puts the replies with the same text into one group.

`smtp_response_group` is available in `group_by` only. You cannot filter on it. To limit a query to one type of reply, filter on `smtp_code`, `enhanced_status_code`, or `bounce_classification`.

A group that has no stored reply has the value `null`.

## Infrastructure dimensions

These dimensions describe the IP addresses that sent your email.

| Dimension | Value |
| --- | --- |
| `infrastructure_state` | `shared`, `dedicated`, `fallback`, or `unknown`. `fallback` means that your team has dedicated IP addresses, but this email left from a different address. |
| `dedicated_ip` | The dedicated IP address that sent the email. |
| `dedicated_pool_id` | The name of the dedicated IP pool that sent the email. |

`dedicated_ip` and `dedicated_pool_id` show only the dedicated IP addresses of your team. A filter with `is_null` on one of them selects the email that did not leave from your dedicated IP addresses.

Infrastructure dimensions support delivery metrics, feedback metrics, delivery and total latency, opens, clicks, and the rates built from these. They do not support `accepted`, `processed`, `messages`, and the other acceptance metrics, with the exception of `mta_accepted`.

## Engagement dimensions

These dimensions describe an open or a click. They support the open and click counts only. Rates are not available.

| Dimension | Value |
| --- | --- |
| `engagement_state` | The confidence that a person made the request: `high_confidence_human`, `likely_human`, `inferred_human`, `machine`, or `unknown`. |
| `request_actor` | `human` or `machine`. |
| `proxy_type` | The proxy that made the request, when Lettermint can identify it. The set of values can grow. |

You can combine engagement dimensions with all traffic dimensions and all infrastructure dimensions.

### Engagement class filters

`is_human`, `is_privacy`, `is_bot`, and `is_scanner` limit open and click metrics to one [class](/platform/analytics/metrics#opens-and-clicks). They have special rules:

- They are available in `filters` only.
- The only value is `"1"`, with the operator `eq`.
- A query can use one of them.

Use these filters with the `observed_` metrics. With `is_privacy`, the metric `observed_opens` returns the opens through a privacy proxy. This is the same number as `privacy_opens` without a filter.

## Dimensions that change what is counted

The mail server of Lettermint selects a mailbox provider and an IP address at each delivery attempt. Before the first attempt, a recipient has no provider and no IP address.

For that reason, three things change when a query groups by or filters on one of these dimensions:

`provider_family`, `provider_subtype`, `infrastructure_state`, `dedicated_ip`, `dedicated_pool_id`, and all SMTP dimensions.

1. `mta_accepted` and `attempted_recipients` return the number of delivery attempts. They have the same value as `delivery_attempts`. A recipient that was deferred twice and then delivered counts three times.
2. The metrics `accepted`, `processed`, `messages`, `suppressed`, `policy_rejected`, `application_failed`, and `canceled` have no value. These events happen before the first attempt. With a provider dimension, they return `null`. With an infrastructure or SMTP dimension, the API rejects them with status `422`.
3. A breakdown leaves out the group without a value. The rows of the breakdown can add up to less than the summary.

The summary of a query is not affected by `group_by`. Only filters change the summary.

:::tip
To compare the volume that you sent with the result per provider, use two metrics that are both counted per attempt: `delivery_attempts` and `delivered`.
:::

## Which dimensions work together

A query can use up to three dimensions in `group_by` and up to 20 filters. Each metric in the query must support each dimension in the query. This table shows the combinations.

| Dimension group | Combines with | Metrics |
| --- | --- | --- |
| Traffic | Every group, within the limits of that group | All |
| Tags | `project_id`, `route_id`, `message_type`, `sending_domain`, `provider_family` | All except opens, clicks, and their rates |
| From address and subject | `project_id`, `route_id`, `message_type` | All except opens, clicks, and their rates |
| SMTP | Traffic and infrastructure | Delivery counts only |
| Infrastructure | Traffic, SMTP, and engagement | Delivery, feedback, latency, opens, and clicks |
| Engagement | Traffic and infrastructure | Open and click counts only |

When a combination is not possible, the API returns status `422`. The message names the metric and the dimension that do not work together.

## Filters

A filter has a dimension, an operator, and values. All values are strings. Lettermint compares them exactly, and the comparison is case-sensitive.

| Operator | Values | Selects |
| --- | --- | --- |
| `eq` | One | Email where the dimension has this value |
| `in` | One or more | Email where the dimension has one of these values |
| `not_in` | One or more | Email where the dimension has a value that is not in this list. Email without a value is left out. |
| `is_null` | None | Email where the dimension has no value |
| `is_not_null` | None | Email where the dimension has a value |

A query combines its filters with AND. To get OR for one dimension, use `in` with several values.

`project_id` and `route_id` accept UUIDs only. `smtp_code` accepts three-digit codes only.

## Next steps

- [Metrics](/platform/analytics/metrics). Read the definition of each metric.
- [Query analytics with the API](/platform/analytics/query). Build a query with these dimensions.
- [Examples](/platform/analytics/examples). See complete queries for common questions.
