Skip to content
ChangelogBook a demoSign up

Reporting

AudienceMarketers, lifecycle and CRM teams, data teams

Native Delivery reports on sends in the app and writes every event back to your warehouse, so you can build your own audiences and reports on top of them.

Review a message's performance

The Engagement card on a message or campaign shows three metrics:

MetricWhat it counts
SentMessages handed off for delivery.
OpenedShare of messages opened, counted once per recipient.
ClickedShare of messages with a link clicked, counted once per recipient.

Opens and clicks here exclude machine and bot activity, including the prefetching that security scanners and mail privacy features perform. Each recipient counts once, so these measure how many people engaged, not how many times.

Three things mark activity as machine-generated: a known security-scanner signature, engagement within two seconds of the send, and the mail provider's own machine-open signal. That last one catches privacy features that load images automatically. Opens through Gmail's and Yahoo's image proxies are counted as real, because a person did open the message even though the request comes from the provider's servers.

These numbers are lower than the raw counts other platforms report, which usually include bot opens and count repeats. Compare your own trends over time instead of matching rates across platforms.

Engagement over time charts the same three metrics, and the Link clicks table breaks clicks down by URL with unique and total counts.

See who didn't receive a message

Recipients Hightouch withheld a message from are reported with a reason for each:

ReasonWhat happened
Not subscribed to topicUnsubscribed from the topic, or never confirmed an opt-in.
Channel unsubscribedOpted out of all email.
Previously bouncedA previous email to this address bounced.
SuppressedA previous spam complaint, or a suppression rule.
Invalid recipientThe address isn't a usable email address, so nothing was sent. Different from a bounce, where an address looked valid and delivery failed.
Quiet hoursThe send fell in your quiet hours window.
Repeat sendAlready received this message, and repeats aren't allowed.
User frequency limitAlready at their message limit for the period.
Volume capThe message hit its total cap.
Channel daily capThe workspace hit its daily limit for email.
ExpiredA send with a Duration window didn't reach them inside it.

These reasons explain a send that reached fewer people than expected. A high Not subscribed to topic count points at consent. A high Previously bounced count points at list quality.

A bounced address is suppressed permanently. There's no retry window. An address that bounced once won't be tried again.

Query the events in your warehouse

Hightouch writes five event tables into your warehouse, each suffixed with your workspace ID. Every row is one event tied to a recipient and a message.

TableWhat it records
cep_dispatcher_eventsWhat Hightouch attempted: sent, dropped, and failed.
cep_deliverability_eventsDelivery outcomes: delivered and bounced.
cep_engagement_eventsOpens, clicks with the clicked URL, and spam reports.
cep_consent_eventsSubscription changes by topic.

Events land in your warehouse within about 15 minutes.

Managed models sit on top of these tables, already filtered and labeled, one per event type: Email delivered, Email opened, Email clicked, Email bounced, Email unsubscribed. Each is keyed on your parent model's primary key, so you can build an audience like "opened an email in the last 30 days" without writing SQL.

Query the raw tables directly for custom analysis, your own dashboards, or anything the managed models don't cover.

Table schemas

Every table carries the same identity and timestamp columns, listed with each table below. Use timestamp for time-based analysis, provider_event_type to filter to a specific event, and parent_model_pk to join back to your customer data.

Dispatcher events

What Hightouch attempted to send, written at send time. One row per recipient per send attempt.

ColumnDescription
idUnique row identifier, for de-duplicating
timestampWhen the event happened. Use this for time filters
provider_event_typeThe event, such as delivered, bounce, open, click
channel_typeemail or sms
parent_model_pkThe recipient's primary key from your parent model
user_handleThe recipient's email address or phone number
message_idThe message this event belongs to
message_execution_idThe specific send this event belongs to
campaign_idThe campaign. Empty for journey sends
campaign_run_idThe campaign run. Empty for journey sends
message_nameThe name of the message
journey_idThe journey. Empty for messages sent from a campaign
journey_nameThe name of that journey
subjectThe rendered subject line this recipient received
preheaderThe rendered preview text
from_emailThe address the message was sent from
from_nameThe display name the message was sent from
drop_reasonWhy the recipient was skipped. Only set on dropped rows

Deliverability events

What happened after handoff: whether the message reached the recipient's mail server.

ColumnDescription
reasonWhy the message bounced or was dropped
responseThe receiving mail server's response
bounce_classificationBounce category, such as invalid address or reputation
statusSMTP status code for the attempt
attemptWhich retry attempt this was
domainRecipient domain, useful for per-provider analysis

Engagement events

What recipients did with the message: opens and clicks.

ColumnDescription
urlThe exact URL clicked. Empty on opens
url_normalizedSame URL with tracking parameters stripped, better for grouping
useragentMail client or browser that generated the open or click
inferred_tzRecipient timezone, where it could be determined

Every change to a recipient's subscription preferences. Append-only, which preserves the full history.

ColumnDescription
topic_idThe subscription topic. Empty means the change applied to the whole channel
consent_statusThe resulting state, subscribed or unsubscribed. Read this one
updated_byWho made the change
updated_by_sourceWhere it came from, such as the preference page or a one-click unsubscribe

FAQ

Why is a column missing from my table?

Hightouch creates a column the first time an event carries a value for it. A workspace that has never recorded a particular event won't have its columns yet, and they appear once the first matching event arrives.

Why do I see columns that aren't listed here?

These tables aren't a fixed schema. Additional detail reported during delivery is written as extra columns. Your tables may hold more than what's documented above.

Which timestamp should I use?

Use timestamp. The other timestamp columns record when the event moved through each stage of collection, and are mainly useful for diagnosing delays.

SMS reporting

SMS reports on sends and clicks. There's no open tracking for text messages.

MetricWhat it counts
SentMessages handed off for delivery
DeliveredShare that reached the recipient's handset
ClickedShare where the link was clicked

There's no Opened metric for SMS. Nothing in a text message reports that it was read, so clicks are your engagement signal. Click rate here is a share of messages sent.

The Deliverability page has an SMS tab with Sent, Delivered, Send failed, Clicked, Subscribed, and Unsubscribed.

A high Quiet hours (no timezone) count means your parent model is missing time zone data.

SMS writes to the same event tables. cep_engagement_events holds clicks, with short_id and user_agent on each row. STOP and START land in cep_consent_events alongside every other preference change.

Next steps

Ready to get started?

Jump right in or a book a demo. Your first destination is always free.

Book a demoSign upBook a demo

Need help?

Our team is relentlessly focused on your success. Don't hesitate to reach out!

Feature requests?

We'd love to hear your suggestions for integrations and other features.

Privacy PolicyTerms of Service