Beta Feature: Matik Analytics is currently in beta. Contact your Technical Account Manager if you are interested in access.
Matik Analytics lets you query the usage and engagement data Matik already collects about your enterprise, the same way you query a data warehouse or a CRM. You write SQL against a small set of curated tables, and the results become Dynamic Content or Input options like any other data source.
There is nothing to connect. Matik Analytics is not in the list of data sources you add under Connect Data Source, and it needs no credentials, no host, and no permissions setup. Once it is enabled for your enterprise, it appears in the data source picker on its own.
Every query is automatically scoped to your own enterprise. You never write a filter to limit results to your company's data, and there is no way to see another company's.
Example Use Cases
Report on Matik usage in the format your team already uses
Instead of exporting a fixed CSV and reshaping it, query the data directly and get exactly the columns and grouping you need.
For example, to build a monthly adoption slide for standalone, non-email presentations, aggregate presentation activity by month and user group. A user can belong to more than one group, so presentation_counts stores group membership as a comma-joined list. Split that list into one row per group before grouping:
WITH group_rows AS (
SELECT
DATE_TRUNC('month', p.created_on) AS month,
ids.id AS user_group_id,
names.name AS user_group,
p.total_presentations
FROM presentation_counts p
CROSS JOIN unnest(string_to_array(p.user_group_ids, ',')) WITH ORDINALITY AS ids(id, pos)
JOIN unnest(string_to_array(p.user_groups, ',')) WITH ORDINALITY AS names(name, pos)
ON names.pos = ids.pos
WHERE p.created_on >= CURRENT_DATE - INTERVAL '6 months'
AND p.is_attachment = FALSE
AND p.template_source_type <> 'email'
)
SELECT
month,
user_group_id,
MAX(user_group) AS user_group,
SUM(total_presentations) AS presentations
FROM group_rows
GROUP BY month, user_group_id
ORDER BY month, presentations DESCAs with any other piece of Dynamic Content, the result can drive a table, a chart, or an Insights summary.
Follow up with the recipients who engaged
Matik Analytics allows you to leverage your own Matik Mail performance analytics to drive personalization. For example, after a campaign, you may want to send a targeted follow-up only to people who showed interest. A Matik Analytics query returns the recipients who clicked in the last 30 days:
SELECT DISTINCT recipient_email
FROM email_events
WHERE event_type = 'click'
AND occurred_at >= CURRENT_DATE - INTERVAL '30 days'
AND flow_name = &:flow_nameReference that Dynamic Content inside a query on your own contacts data to build the follow-up list:
SELECT email
FROM contacts
WHERE email IN (
SELECT recipient_email
FROM {{recently_engaged_recipients}}
)This works in both directions. A Matik Analytics query can be nested inside another data source's query, and another data source's Dynamic Content can be nested inside a Matik Analytics query.
Selecting Matik Analytics as a Data Source
Matik Analytics can be used to power Dynamic Content or Inputs, just like any other data source. Once the beta is enabled for your enterprise, select Matik Analytics as the data source.
Querying Matik Analytics
Matik Analytics is organized into Analytics Categories. Each category contains related tables that you can query.
| Category | Included Data | Tables | Requires |
|---|---|---|---|
| Email analytics | Sends and engagement for emails your enterprise has sent through Matik. | email_sends, email_events | Matik Mail |
| Generation performance | Timing for each step of the presentations your enterprise has generated. | generation_times, generation_times_daily | None |
| Presentation activity | Who creates presentations, from which templates, and how that changes over time. | presentation_counts | None |
The dropdown only lists categories your enterprise can use.
A single query reads from one category, so you cannot join a table in Email analytics to a table in Presentation activity. To combine them, build separate Dynamic Content for each and reference one inside the other.
Email Analytics
Available to enterprises with Matik Mail enabled.
email_sends - one row per recipient of a sent email, with delivery state and engagement totals.
| Column | Type | Description |
|---|---|---|
sent_at | timestamp | When the send record was created. |
recipient_email | text | Email address the message was sent to. |
recipient_type | text | Whether the recipient was on the to, cc, or bcc line. |
template_name | text | Name of the email template used. |
flow_name | text | Name of the scheduled flow that sent it, if any. |
delivery_status | text | Delivery outcome for the message. |
open_count | integer | Number of times this recipient opened the message. |
click_count | integer | Number of link clicks by this recipient. |
unsubscribed | boolean | Whether the recipient unsubscribed from this send. |
spam_report | boolean | Whether the recipient reported the message as spam. |
last_open_at | timestamptz | Most recent open, or null if never opened. |
last_click_at | timestamptz | Most recent click, or null if never clicked. |
email_events - one row per email engagement event, either an open or a click.
| Column | Type | Description |
|---|---|---|
event_type | text | The kind of engagement, such as open or click. |
occurred_at | timestamptz | When the event happened. |
recipient_email | text | Email address that generated the event. |
recipient_type | text | Whether the recipient was on the to, cc, or bcc line. |
template_name | text | Name of the email template used. |
flow_name | text | Name of the scheduled flow that sent it, if any. |
url | text | Clicked URL. Null for opens. |
attachment_id | integer | Id of the clicked attachment. Null for opens and non-attachment clicks. |
attachment_name | text | Name of the clicked attachment. Null for opens and non-attachment clicks. |
attachment_template_id | integer | Template id of the clicked attachment. Null when there is none. |
attachment_template_name | text | Template of the clicked attachment. Null when there is none. |
Generation Performance
How long each step of a presentation generation takes. Use generation_times_daily for reporting and generation_times when you need individual runs.
generation_times - one row per pipeline step of a presentation generation, with its elapsed time.
| Column | Type | Description |
|---|---|---|
occurred_on | date | Day the generation ran. |
event_name | text | Pipeline step that reported this timing. |
elapsed_ms | bigint | How long the step took, in milliseconds. |
generation_times_daily - daily rollup of generation timings per pipeline step: run count, median, and 95th percentile.
| Column | Type | Description |
|---|---|---|
occurred_on | date | Day the runs happened. |
event_name | text | Pipeline step that reported these timings. |
runs | integer | Number of times the step ran that day. |
p50_ms | numeric | Median elapsed milliseconds across the day's runs. |
p95_ms | numeric | 95th percentile elapsed milliseconds across the day's runs. |
Presentation Activity
presentation_counts - daily presentation generation counts. One row per UTC day, user, template, and whether the row counts rendered email attachments.
| Column | Type | Description |
|---|---|---|
created_on | date | UTC day the presentations were created. The current partial day is dropped, so days are only ever complete. |
user_id | integer | Id of the user who created the presentations. |
user_name | text | Name of the creating user, as of the row's last sync. |
user_email | text | Email of the creating user. |
user_group_ids | text | Comma-joined ids of the groups the user belongs to. The stable key for group filters. |
user_groups | text | Comma-joined names of the groups the user belongs to, in the same order as user_group_ids. Display text, as of the row's last sync. |
is_producer | boolean | Whether the user holds a non-consumer role. Matched by role name, so custom roles count. |
template_id | integer | Id of the template the presentations were generated from. |
template_name | text | Name of the template, as of the row's last sync. |
template_source_type | text | Kind of template: powerpoint, google_slides, email, and so on. email marks email shell rows. |
is_attachment | boolean | Whether the row counts presentations rendered as email attachments. |
total_presentations | bigint | Completed presentations created that day. Test runs and Mail Outbox previews are excluded, and deleted presentations still count. |
total_failed | bigint | Presentations that failed that day through an error, a failed condition, or a timeout. |
Note: An email send creates a shell row (template_source_type = 'email') plus a row for each rendered attachment. Filter on is_attachment or template_source_type so sends are not counted twice.
Writing Queries
Matik Analytics accepts one read-only PostgreSQL query at a time. Start your query with SELECT or WITH ... SELECT, and use only the tables listed for the selected Analytics Category.
Matik Analytics supports referencing &:inputs and {{nested_dc}}, just like any other SQL query in Matik. These references can be used anywhere their resolved values are valid, including using nested table Dynamic Content in a FROM or JOIN clause. Matik Analytics Dynamic Content can also be nested in another SQL data source that supports table Dynamic Content.
Supported SQL
- Joins between tables in the same Analytics Category
- Subqueries and common table expressions (CTEs), including recursive CTEs
- Aggregates and window functions
- Set operations such as
UNION,INTERSECT, andEXCEPT - Standard PostgreSQL expressions and functions, except for the restricted operations described below
SQL that is not supported
- More than one SQL statement in a query. A single trailing semicolon is allowed.
- Statements that write data or modify the database, including
INSERT,UPDATE,DELETE,MERGE,CREATE,DROP,ALTER, andTRUNCATE - Database administration or session commands, including
GRANT,REVOKE,COPY,SET,EXPLAIN,SHOW, andVACUUM - Locking or table-creation forms such as
FOR UPDATEandSELECT INTO - Schema-qualified table names, such as
public.email_sends - System catalogs, raw Matik application tables, or tables from another Analytics Category
- A CTE that uses the same name as one of the category's built-in tables
- Functions that inspect or modify the database server or session, access server files, open external database connections, or pause or control database processes
Matik validates each query before it runs and displays an error when the query uses unsupported SQL.
You can also ask the Matik AI Agent to write or update an analytics query for you, rather than authoring the SQL yourself.
Limitations
- Data is not real time. Analytics data syncs throughout the day and is typically less than two hours behind the activity it describes. In
presentation_counts, the current partial day is always excluded, so the most recent day you can query is the last complete UTC day. - One statement per query. A second statement after a semicolon is rejected.
- One category per query. Tables from different categories cannot be joined in a single query.
- Query text is limited to 1 MB.
- Query timeout. Matik Analytics queries that run longer than 60 seconds are stopped.
- Saved results. A saved query result holds up to 50,000 rows.
Best Practices
- Filter out attachment rows when counting unique sends. In
presentation_counts, an email send produces both an email row and attachment rows. Without a filter onis_attachmentortemplate_source_type, the query will count both the email and any attachments. - Split group membership before you group by it.
user_group_idsanduser_groupsare comma-joined lists, so grouping on either column groups by the whole combination of a user's groups rather than by one group at a time. Split them into one row per group first, as in the example above. Note that this drops users who belong to no group; switch theCROSS JOINto aLEFT JOIN ... ON trueif you need those rows. - Group by
user_group_ids, displayuser_groups. Group names change and are stored as of the last sync. The ids are stable, so group on those and use the names for display. - Use
generation_times_dailyfor trends. It is already rolled up per day and step, so it returns far fewer rows thangeneration_timesand stays well clear of the saved-result cap. - Use nested Dynamic Content to query across Analytics Categories. Since a query reads from a single category, combining email and presentation data means referencing one Dynamic Content inside another.
Comments
0 comments
Please sign in to leave a comment.