Events API¶
Every offer or ad that the Fetch API returns produces a stream of events: the fetch itself, message lifecycle notifications, taps on tracked links and replies, the customer's response to an offer, and conversions. Events drive the counts in the console's reports, and responses feed the subscriber history that rules read. This page describes the event types, how to report them, how conversions are tracked, and how responses are recorded.
How events are linked¶
Every event belongs to the org that owns the API key of the original fetch.
An event is linked to the fetch that returned the offer or ad by the
fetch identifier, the messageId in the
fetch response. You pass that value as fetchEventId
when you report an event, which ties deliveries, clicks, and conversions to
a specific offer, rule, and moment.
An event can also carry the subscriber identifier from the fetch request,
which counts unique reach and enforces frequency caps.
Event types¶
| Event type | Description | How it is recorded |
|---|---|---|
fetch |
An offer or ad was returned. | Automatically, by the Fetch API. |
send |
The message with the offer or ad was sent. | Reported by your application. |
deliver |
The message reached the customer's device. | Reported by your application. |
read |
The customer read the message. | Reported by your application. |
click |
The customer followed a tracked link. | Automatically, by the click-tracking redirect, or reported by your application. |
conversion |
The customer completed the tracked action, such as a booking or a purchase. | Reported by your application, by a conversion pixel, or by an offline upload. |
offer_accepted |
The customer accepted the offer. | Reported by your application. See Responses to an offer. |
offer_declined |
The customer turned the offer down. | Reported by your application. See Responses to an offer. |
Flow ads add six event types of their own.
Report an event¶
Send a POST with your API key, as the query parameter key or in the
Authorization header:
POST https://ads.advertising.chat/v1/event
Content-Type: application/json
{
"version": 2,
"eventType": "deliver",
"fetchEventId": "<messageId from the fetch response>",
"timestamp": 1720000000000,
"subscriber": "<opaque subscriber id>",
"eventData": { }
}
| Field | Description |
|---|---|
version |
Required. Must be 2. |
eventType |
Required. One of send, deliver, read, click, conversion, offer_accepted, or offer_declined, or a flow event. |
fetchEventId |
Required. The messageId from the fetch. An event that can't be linked to a fetch is rejected. |
timestamp |
Optional. When the event happened, in Unix epoch milliseconds. |
subscriber |
Optional. Used only if the fetch request had no subscriber. |
eventData |
Optional. JSON to store with the event, available in the journal. |
A 201 Created response confirms the event. An invalid eventType,
eventData, or fetchEventId returns 422 Unprocessable Entity, as does an
offer_accepted or offer_declined event that can't be
resolved.
Click tracking¶
Links in returned offers and ads are click-tracking URLs, usually shortened
on ads.chat. When the customer opens one, Advertising.chat records a
click event and redirects to the original destination with a 302. Your
application doesn't need to do anything to track these clicks.
Conversion tracking¶
Conversion pixel¶
To record conversions on a page that the customer reaches after a click, such as an order confirmation, embed this pixel:
GET https://ads.advertising.chat/v1/event?key=<your API key>&name=<activity>&value=<value>&cur=<currency>
The request returns a 1×1 transparent GIF. name identifies the activity,
and value and cur optionally record its monetary value and currency.
The pixel records a conversion on every load. When the customer reached
the page through a tracked link in the past week, the conversion is
attributed to that click.
Offline conversions¶
To upload a conversion that happened outside the conversation, such as at a front desk or in a call center, send:
POST https://ads.advertising.chat/v1/event/offlineConversion
Content-Type: application/json
{
"messageId": "<messageId from the fetch response>",
"eventData": { }
}
A 200 response confirms the upload.
A conversion attributed to a fetch also records converted in the
customer's subscriber history. See
Conversions.
Responses to an offer¶
A response is how a customer answered an offer: accepted,
declined, or converted. Responses are recorded in the customer's
subscriber history, where rules read them, for
example to stop showing an offer to anyone who turned it down in the last 30
days. A response is recorded in one of three ways:
- Your agent reports a tap on a reply that has a role, to
/v1/interact. - Your application reports an
offer_acceptedoroffer_declinedevent, to/v1/event. - A conversion is attributed to the fetch.
Each response names the fetch it answers by its fetch identifier. The
fetch is looked up in your org's fetch journal, which keeps fetches for
seven days, and resolves to the fetch's agent, subscriber, rule, and offer.
A fetch that is older than seven days or that had no subscriber can't be
resolved, and no response is recorded for it.
Silence is not a decline. A customer who doesn't answer an offer has no
declined event, so a rule that excludes decliners keeps showing the offer
to them.
Reply roles¶
A reply role says what tapping one of an offer's replies means. Each
entry of a creative's actions can carry a role:
role |
A tap records |
|---|---|
accept |
accepted, for the offer and the rule that served it. |
decline |
declined, for the offer and the rule that served it. Use it on a reply such as "Not now". |
| Absent | Nothing in subscriber history. The tap is recorded as an interaction only. |
Each action in a rendered offer has an action ID,
<offer shortid>-<index>, where index is the action's position in the
creative's actions, starting at 0. Its postback data is
<messageId>_<actionId>: the fetch identifier, an underscore, and the action
ID. In the RCS formats, the postback data is the suggestion's postback data,
which the RCS platform returns to your agent when the customer taps it. In
the fbm format, it is the quick reply's payload, which Messenger returns as
message.quick_reply.payload. In the direqt format, each action carries it as context, with the action ID
in actionId.
Report a reply tap¶
When the customer taps a reply, send its postback data unchanged:
postbackData is a query parameter, URL-encoded. The response is a 200
with this body:
| Field | Description |
|---|---|
actionId |
The action ID from the postback data. |
role |
The tapped reply's role, when it has one. |
recorded |
The response recorded in subscriber history, accepted or declined. Absent when the reply has no role, when the fetch can't be resolved, when that fetch didn't serve the offer, or when the same reply was already recorded for that fetch. |
Postback data that isn't <messageId>_<actionId> returns 422.
Link replies¶
A reply that opens a web page (actionType: "Navigate") links through the
click redirect, https://ads.advertising.chat/v1/click, and the link
carries the reply's postback data. When the customer follows the link, the
reply's role is recorded as it is for a reported tap, so your agent doesn't
need to report it on /v1/interact. A reply's role is recorded once per
fetch, however often the link is followed or the tap reported. Link previews that messaging apps and
crawlers fetch record nothing.
Report an accept or a decline¶
When your agent learns the customer's answer some other way, such as from a free-text reply, report it as an event against the fetch. The event takes either of two bodies. The version 2 body:
POST https://ads.advertising.chat/v1/event?key=YOUR_API_KEY
Content-Type: application/json
{
"version": 2,
"eventType": "offer_declined",
"fetchEventId": "<messageId from the fetch response>",
"eventData": { "offer": "<creative ID>" }
}
It returns 201 when the response is recorded, and 422 with no body
when it isn't.
The event-name body:
POST https://ads.advertising.chat/v1/event?key=YOUR_API_KEY
Content-Type: application/json
{
"messageId": "<messageId from the fetch response>",
"eventName": "offer_declined",
"eventData": { "offer": "<creative ID>" }
}
It returns 200 with { "eventId": "<id>", "recorded": "declined" } when
the response is recorded. When it isn't, it returns 422 with a message
and a reason:
reason |
Meaning |
|---|---|
unknown-message |
The fetch identifier is invalid, isn't a fetch of your org, or is older than seven days. |
no-subscriber |
The fetch had no subscriber. |
no-offer |
The fetch served no offer, or eventData.offer isn't a valid ID. |
unknown-offer |
eventData.offer isn't an offer that the fetch served. |
In both bodies, eventData.offer is optional. It picks one of the offers
the fetch served, and defaults to the first.
Conversions¶
A conversion attributed to a fetch records converted for the fetch's
offer and rule. That covers each conversion event reported to
/v1/event, and the first conversion that the
conversion pixel or an
offline upload attributes to a fetch. A conversion
whose fetch can't be resolved is still recorded as an event.
Subscriber history¶
Subscriber history is the record of one customer's offer events, kept
for each subscriber identifier within each agent. An agent's rules read
only that agent's history. A request without a subscriber has no history.
| Event | Recorded for | When |
|---|---|---|
shown |
The moment, the rule, and the offer | A fetch with a subscriber returns an offer. Test requests aren't recorded. For an exchange rule, only the moment and the rule. |
accepted, declined |
The offer and the rule that served it | A reply tap with a role, or an offer_accepted or offer_declined event. |
converted |
The offer and the rule that served it | A conversion attributed to the fetch. |
For each moment, rule, or offer and each event type, history keeps the 20 most recent events, and none older than 95 days. A customer's history expires 95 days after its last event.
Three parts of serving read it:
- Frequency caps on moments, rules, and offers count
shownevents. See Frequency. - History conditions in a rule's
audienceandexclusionscount events of any type. See History conditions. - A rule that shows its offers in turn (Show them in turn, in this order) keeps each customer's place in its offers.
Because history keeps 20 events per type, a frequency cap allows at most 20 serves, and a history condition requires at most 20 events. Their windows are at most 90 days, inside the 95 days that history keeps.