Conversions
Count the events that matter, such as a subscription or a purchase, and credit each one to the email that earned it.
A conversion goal names an event your app already sends, such as subscription_started. From the moment the goal exists, every event with that name is also recorded as a conversion and credited to the last email the person clicked within the goal's window (7 days unless you choose otherwise). Campaign, A/B variant and automation step reports then show conversions, converters and revenue beside opens and clicks.
How the credit is decided:
- Last click. The conversion goes to the most recent email the person clicked before it, within the window. It is a rule you can predict and check, and the one most email tools use.
- Only a person's click. Corporate security gateways open every link in a message within a second of delivery. Those clicks are recognised and never earn credit, so a scanner cannot claim a sale.
- Opens never count. Apple Mail fetches every image when a message arrives, so an "open" there says nothing about a person.
- Attributed, not caused. A credited email is the last one the person clicked. It is not proof the email made them buy, and the dashboard says "attributed" for that reason.
A conversion starts pending and is credited a few seconds after it arrives, once every click that could earn it has been checked for scanners. With no click by a person in the window it becomes unattributed: it is kept and listed, and counted in no report. Events received before a goal existed are not counted.
Create a conversion goal
POST /v1/conversion-goals · requires broadcasts:write
Body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
event_name | string | yes | 1 to 120 characters, matched exactly (including case) against name on POST /v1/events. | |
window_days | integer | no | 7 | 1 to 30. How many days before the conversion a click may be and still earn the credit. |
A workspace can have up to 50 goals.
Example
Response
201 Created
Errors
| Status | Type | When |
|---|---|---|
| 409 | conflict | This event name is already a goal. List goals shows it with its id. |
| 422 | invalid_request | The body failed validation, or the workspace already has 50 goals. |
List conversion goals
GET /v1/conversion-goals · requires broadcasts:read
Every goal, oldest first, in the list envelope. Not paged: next_cursor is always null.
Retrieve a conversion goal
GET /v1/conversion-goals/{id} · requires broadcasts:read
Answers the goal, or 404 not_found.
Change a goal's window
PATCH /v1/conversion-goals/{id} · requires broadcasts:write
Takes window_days (1 to 30) and nothing else. The new window applies to conversions not yet credited. One already credited keeps its email, so a report never changes under someone reading it. The event name cannot change; create a new goal instead.
Delete a conversion goal
DELETE /v1/conversion-goals/{id} · requires broadcasts:write
Deletes the goal and every conversion recorded against it. They cannot be restored. The event keeps working as an ordinary event, and automations it starts are unaffected.
Record a conversion
Send the goal's event to POST /v1/events, with value and currency when there is an amount and your own id so a repeat is counted once:
The response's conversion_id names the conversion.
Conversion metrics
GET /v1/conversions/metrics · requires broadcasts:read
Credited conversions, distinct converters and revenue per currency. Scoped to one campaign it adds the messages sent and the conversion rate, and a row per variant for an A/B test. Scoped to one automation, a row per step.
The rate is converters / sent: it counts people, so one reader buying twice does not double it. Revenue counts every purchase. Values in different currencies are never added together. Pending and unattributed conversions are not counted.
Query parameters
| Parameter | Description |
|---|---|
goal_id | Only this goal. All goals when left out. |
broadcast_id | Only conversions credited to this campaign. Not with automation_id. |
automation_id | Only conversions credited to this automation. Not with broadcast_id. |
from, to | ISO 8601 times. Conversions received at or after from and before to. |
Response
200 OK, for an A/B test campaign:
sent and conversion_rate are null unless broadcast_id or automation_id is given. by_variant is null unless the campaign is an A/B test, and by_step unless automation_id is given. A step row has step (its position now, numbered from 1) and step_id in place of key. Figures follow the step id, so a step keeps its own conversions when the sequence is edited; automation_step on a conversion is the position when the email was sent.
Errors
| Status | Type | When |
|---|---|---|
| 404 | not_found | goal_id, broadcast_id or automation_id names nothing in the workspace. |
| 422 | invalid_request | A filter is malformed, or both broadcast_id and automation_id were given. |
List conversions
GET /v1/conversions · requires broadcasts:read
Every recorded conversion, newest first, paged with limit and cursor. Takes the metrics filters above, plus status (pending, attributed or unattributed) and email for one person's conversions.
Retrieve a conversion
GET /v1/conversions/{id} · requires broadcasts:read
Response
message_id, clicked_at, broadcast_id, variant, automation_id, automation_step and automation_step_id are set only when status is attributed, and each is null when it does not apply. A transactional email can be credited too; it has no campaign or automation.