This document describes how to get messaging, conversation, and template analytics, such as the number of messages sent from a business phone number, the number of conversations and their costs for a WhatsApp Business Account (WABA), or the number of times a given template has been read.
Only metrics for business phone numbers and templates associated with your WABA at the time of the request will be included in responses.
Use the WhatsApp Business Account endpoint to get analytics.
GET /<WHATSAPP_BUSINESS_ACCOUNT_ID> ?fields=<FIELDS>.<FILTERING_PARAMETER>
<FIELDS>
analytics
<FILTERING_PARAMETERS>
Required.
Metric filtering parameter. Append additional filtering parameters using dots.
For possible values, see:
.start(1543543200).end(1544148000).granularity(DAY)
The analytics
field provides the number and type of messages sent and delivered by the phone numbers associated with a specific WABA — for conversation metrics, see Conversation Analytics
. When calling /{whatsapp-business-account-ID}?fields=analytics.{filtering-parameters}
, you can attach the following parameters.
start
type: UNIX Timestamp
Required.
The start date for the date range you are retrieving analytics for.
end
type: UNIX Timestamp
Required.
The end date for the date range you are retrieving analytics for.
granularity
type: String
Required.
The granularity by which you would like to retrieve the analytics.
Supported Options
HALF_HOUR
DAY
MONTH
phone_numbers
type: Array
Optional.
An array of phone numbers for which you would like to retrieve analytics. If not provided, all phone numbers added to your WABA are included.
product_types
type: Array
Optional.
The types of messages (notification messages and/or customer support messages) for which you want to retrieve notifications. Provide an array and include 0
for notification messages, and 2
for customer support messages. If not provided, analytics will be returned for all messages together.
country_codes
type: Array
Optional.
The countries for which you would like to retrieve analytics. Provide an array with 2 letter country codes for the countries you would like to include. If not provided, analytics will be returned for all countries you have communicated with.
Scenario:You need to get the number of messages sent and delivered by all phone numbers associated with your WABA.
Suggested Solution: Assemble the URL you want to call
and include the following filtering parameters: start
, end
, granularity
. Then, make a GET
request to that URL:
curl -i -X GET \
"https://graph.facebook.com/ v21.0
/{whatsapp-business-account-ID}
?fields=analytics
.start(1543543200)
.end(1544148000)
.granularity(DAY)
&access_token={access-token}"
A successful response returns an analytics
object with the data you have requested:
{ "analytics": { "phone_numbers": [ "16505550111", "16505550112", "16505550113" ], "country_codes": [ "US", "BR" ], "granularity": "DAY", "data_points": [ { "start": 1543543200, "end": 1543629600, "sent": 196093, "delivered": 179715 }, { "start": 1543629600, "end": 1543716000, "sent": 147649, "delivered": 139032 }, { "start": 1543716000, "end": 1543802400, "sent": 61988, "delivered": 58830 }, { "start": 1543802400, "end": 1543888800, "sent": 132465, "delivered": 124392 } # more data points ] }, "id": "102290129340398" }
The conversation_analytics
field provides cost and conversation
information for a specific WABA. When calling /{whatsapp-business-account-ID}?fields=conversation_analytics.{filtering-parameters}
, you can attach the following parameters.
start
type: UNIX Timestamp
Required.
The start date for the date range you are retrieving analytics for.
end
type: UNIX Timestamp
Required.
The end date for the date range you are retrieving analytics for.
granularity
type: String
Required.
The granularity by which you would like to retrieve the analytics.
Supported Options
HALF_HOUR
DAILY
MONTHLY
phone_numbers
type: Array
Optional.
An array of phone numbers for which you would like to retrieve analytics. If not provided, all phone numbers added to your WABA are included.
metric_types
Optional.
List of metrics you would like to receive. If you send an empty list, we return results for all metric types.
Supported Options {#supported}
COST
: Includes approximate charges for that time range, in the WABA’s currency.CONVERSATION
: Includes the count of conversations for that time range. As of July 1, 2023, COST
is no longer shown for businesses who bill through a Solution Partner.To understand your charges, please reach out to your partner. If you bill through a partner, this is the behavior to expect:
metric_types
are specified in your request, only CONVERSATION
is returnedCONVERSATION
is specified, only CONVERSATION
is returnedIf you query a time period that includes dates on or after July 1, 2023, (e.g., May 1, 2023 through August 1, 2023), the response will include the exception above.
There is no change for partners when querying theconversation_analytics
endpoint.
conversation_categories
Optional.
List of conversation categories . If you send an empty list, we return results for all conversation categories.
Supported Options
AUTHENTICATION
MARKETING
SERVICE
UTILITY
conversation_types
Optional.
List of conversation types. If you send an empty list, we return results for all conversation types.
Supported Options
FREE_ENTRY
: Conversations originating from a free entry point
.FREE_TIER
: Conversations within the monthly free tier
.REGULAR
: Any conversations that did not originate from a free entry point
or are above the monthly free tier allotment. conversation_directions
Optional.
List of conversation directions. If you send an empty list, we return results for all conversation directions.
Supported Options
BUSINESS_INITIATED
: Conversations initiated by the business.USER_INITIATED
: Conversations initiated by an end user/customer. dimensions
Optional.
List of breakdowns you would like to apply to your metrics. If you send an empty list, we return results without any breakdowns.
Supported Options
CONVERSATION_CATEGORY
CONVERSATION_DIRECTION
CONVERSATION_TYPE
COUNTRY
PHONE
Analytics data is approximate and may differ from what’s shown on invoices due to small variations in data processing.
Given a time range, you can get conversation and cost information associated with your WABA. If you want, you can filter and break down your results. See the code samples below for examples.
Scenario:Given a month, you want to retrieve all conversation and cost information for all phone numbers associated with a WABA.
Suggested Solution: Assemble the URL you want to call and include the following filtering parameters:
start
: Start of your time range. In this case, the beginning of the month you want metrics for.end
: End of your time range. In this case, the end of the month you want metrics for.granularity
: How granular you want your data points to be. In the example below, we use MONTHLY
, so each datapoint will represent a month’s worth of data.phone_numbers
: Send an empty array and we return information for all phone numbers associated with the WABA.dimensions
: Set it to all available breakdowns: "CONVERSATION_CATEGORY"
, "CONVERSATION_TYPE"
, "COUNTRY"
, and "PHONE"
.In this case, you do not need to specify country_codes
, metric_types
, conversation_types
and conversation_categories
. If you don't send us anything for those fields, we return all available options. Once you set up the URL, make a GET request:
curl -i -X GET
"https://graph.facebook.com/ v21.0
/{whatsapp-business-account-id}
?fields=conversation_analytics
.start(1685602800).end(1688194800)
.granularity(MONTHLY)
.phone_numbers([])
.dimensions(["CONVERSATION_CATEGORY","CONVERSATION_TYPE","COUNTRY","PHONE"])
&access_token={access-token}"
A successful response returns a conversation_analytics
object with the data you have requested. In the following example, the WABA contains only one phone number.
{ "conversation_analytics": { "data": [ { "data_points": [ { "start": 1685602800, "end": 1688194800, "conversation": 1558, "phone_number": "15550458206", "country": "US", "conversation_type": "REGULAR", "conversation_direction": "UNKNOWN", "conversation_category": "AUTHENTICATION", "cost": 15.58 }, { "start": 1685602800, "end": 1688194800, "conversation": 2636, "phone_number": "15550458206", "country": "US", "conversation_type": "REGULAR", "conversation_category": "MARKETING", "cost": 26.36 }, { "start": 1685602800, "end": 1688194800, "conversation": 2238, "phone_number": "15550458206", "country": "US", "conversation_type": "REGULAR", "conversation_category": "SERVICE", "cost": 22.38 }, { "start": 1685602800, "end": 1688194800, "conversation": 1782, "phone_number": "15550458206", "country": "US", "conversation_type": "REGULAR", "conversation_category": "UTILITY", "cost": 17.82 }, { "start": 1685602800, "end": 1688194800, "conversation": 1568, "phone_number": "15550458206", "country": "US", "conversation_type": "FREE_TIER", "conversation_category": "AUTHENTICATION", "cost": 15.68 }, { "start": 1685602800, "end": 1688194800, "conversation": 2716, "phone_number": "15550458206", "country": "US", "conversation_type": "FREE_TIER", "conversation_category": "MARKETING", "cost": 27.16 }, { "start": 1685602800, "end": 1688194800, "conversation": 2180, "phone_number": "15550458206", "country": "US", "conversation_type": "FREE_TIER", "conversation_category": "SERVICE", "cost": 21.8 }, { "start": 1685602800, "end": 1688194800, "conversation": 1465, "phone_number": "15550458206", "country": "US", "conversation_type": "FREE_TIER", "conversation_category": "UTILITY", "cost": 14.65 }, { "start": 1685602800, "end": 1688194800, "conversation": 1433, "phone_number": "15550458206", "country": "US", "conversation_type": "FREE_ENTRY_POINT", "conversation_category": "SERVICE", "cost": 14.33 } ] } ] }, "id": "102290129340398", }
Scenario: Given a time range, you want to retrieve all conversation and cost information for a specific phone number associated with a WABA. In the results, you want to use all possible breakdowns. You need each data point to represent half an hour’s worth of data.
Suggested Solution: Assemble the URL you want to call and include the following filtering parameters:
start
: Start of your time range.end
: End of your time range.granularity
: How granular you want your data points to be. In the example below, we use HALF_HOUR
, so each datapoint represents half an hour’s worth of data.phone_numbers
: The phone number you need information for.dimensions
: Set it to all available breakdowns: CONVERSATION_CATEGORY
, CONVERSATION_TYPE
, COUNTRY
, and PHONE
.In this case, you do not need to specify country_codes
, metric_types
, conversation_types
, or conversation_categories
. If you don’t send us anything for those fields, we return all available options. Once you set up the URL, make a GET request:
curl -i -X GET \
"https://graph.facebook.com/ v21.0
/{whatsapp-business-account-id}
?fields=conversation_analytics
.start(1685602800)
.end(1685689200)
.granularity(HALF_HOUR)
.phone_numbers(["19195552584"])
.dimensions(["CONVERSATION_CATEGORY","CONVERSATION_TYPE","COUNTRY,PHONE"])
&access_token=your-access-token"
A successful response returns a conversation_analytics
object with the data you have requested:
{ "conversation_analytics": { "data": [ { "data_points": [ { "start": 1685602800, "end": 1685604600, "conversation": 4, "phone_number": "19195552584", "country": "US", "conversation_type": "REGULAR", "conversation_direction": "UNKNOWN", "conversation_category": "SERVICE", "cost": 0.0232 }, { "start": 1685602800, "end": 1685604600, "conversation": 4, "phone_number": "19195552584", "country": "US", "conversation_type": "REGULAR", "conversation_direction": "UNKNOWN", "conversation_category": "MARKETING", "cost": 0.0232 }, # ... more data points ] } ] }, "id": "102290129340398" }
Scenario: Given a time range, you want to retrieve all conversation and cost information for all phone numbers associated with a WABA. In the results, you want to break down by conversation type.
Suggested Solution: Assemble the URL you want to call and include the following filtering parameters:
start
: Start of your time range.end
: End of your time range.granularity
: How granular you want your data points to be. In the example below, we use MONTHLY
, so each datapoint represents half a month’s worth of data.phone_numbers
: Send an empty array and we’ll return information for all phone numbers associated with the WABA.dimensions
: Set it to CONVERSATION_TYPE
.In this case, you do not need to specify country_codes
, metric_types
, conversation_types
, conversation_directions
, or conversation_categories
. If you don't send us anything for those fields, we return all available options. Once you set up the URL, make a GET request:
curl -i -X GET
"https://graph.facebook.com/ v21.0
/{whatsapp-buiness-account-id}
?fields=conversation_analytics
.start(1643702400).end(1646121600)
.granularity(MONTHLY)
.phone_numbers([])
.dimensions([CONVERSATION_TYPE])
&access_token={access-token}"
A successful response returns a conversation_analytics
object with the data you have requested:
{ "data": [ { "data_points": [ { "start": 1643702400, "end": 1646121600, "conversation": 8500, "conversation_type": "REGULAR", "cost": 88.1010 }, { "start": 1643702400, "end": 1646121600, "conversation”: 1000, "conversation_type": "FREE_TIER", "cost": 0.0000 } { "start": 1643702400, "end": 1646121600, "conversation”: 250, "conversation_type": "FREE_ENTRY_POINT", "cost": 0.0000 } ] } ] }
Request:
curl -i -X GET \
"https://graph.facebook.com/ v21.0
/{whatsapp-buiness-account-id}
?fields=conversation_analytics
.start(1685527200)
.end(1685613600)
.granularity(HALF_HOUR)
.conversation_categories(["MARKETING","AUTHENTICATION"])
.dimensions(["CONVERSATION_CATEGORY"])
&access_token={access-token}"
Response:
{ "conversation_analytics": { "data": [ { "data_points": [ { "start": 1685529000, "end": 1685530800, "conversation": 2, "conversation_category": "AUTHENTICATION", "cost": 0.0128 }, { "start": 1685527200, "end": 1685529000, "conversation": 3, "conversation_category": "MARKETING", "cost": 0.0432 } ] } ] }, "id": "102290129340398" }
Request:
curl -i -X GET \
"https://graph.facebook.com/ v21.0
/{whatsapp-buiness-account-id}
?fields=conversation_analytics
.start(1685527200)
.end(1685613600)
.granularity(HALF_HOUR)
.conversation_categories(["MARKETING","AUTHENTICATION"])
.dimensions(["CONVERSATION_CATEGORY","CONVERSATION_TYPE"])
&access_token={access-token}"
Response:
{ "conversation_analytics": { "data": [ { "data_points": [ { "start": 1685527200, "end": 1685529000, "conversation": 3, "conversation_type": "REGULAR", "conversation_category": "MARKETING", "cost": 0.0432 }, { "start": 1685529000, "end": 1685530800, "conversation": 2, "conversation_type": "REGULAR", "conversation_category": "AUTHENTICATION", "cost": 0.0128 } ] } ] }, "id": "102290129340398" }
Pricing analytics will be available to you once per-message pricing applies to your rollout group. See Updates to Pricing .
The pricing_analytics
field allows you to get pricing breakdowns for any messages delivered within a specified date range.
GET /<WABA_ID> ?fields=pricing_analytics .start(<START>) .end(<END>) .granularity(<GRANULARITY>) .phone_numbers(<PHONE_NUMBERS>) .country_codes(<COUNTRY_CODES>) .metric_types(<METRIC_TYPES>) .pricing_types(<PRICING_TYPES>) .pricing_categories(<PRICING_CATEGORIES>) .dimensions(<DIMENSIONS>)
<COUNTRY_CODES>
Array of strings
Optional.
The countries for which you would like to retrieve analytics. Provide an array with 2 letter country codes for the countries you would like to include. If not provided, analytics will be returned for all countries you have communicated with.
[
"US",
"BR"
]
<DIMENSIONS>
Array of strings
Optional.
List of breakdowns you would like to apply to your metrics. If you send an empty list, we return results without any breakdowns.
Values can be:
PRICING_CATEGORY
PRICING_TYPE
COUNTRY
PHONE
[
"PRICING_CATEGORY",
"PRICING_TYPE",
"COUNTRY"
]
<END>
UNIX timestamp
Required.
UNIX timestamp indicating the end date for the date range you are retrieving analytics for.
1728581152
<GRANULARITY>
String
Required.
The granularity by which you would like to retrieve the analytics. Value can be one of:
DAY
HALF_HOUR
MONTH
DAY
<METRIC_TYPES>
Array of strings
Optional.
Array of metrics you would like to receive. If you send an empty array, we return results for all metric types.
Values can be:
COST
: Approximate charges for messages delivered in that time range, in your WABA's currency.VOLUME
: Includes the number of messages delivered for that time range. [
"COST",
"VOLUME"
]
<PHONE_NUMBERS>
Array of strings
Optional.
An array of phone numbers for which you would like to retrieve analytics. If not provided, data for all business phone numbers associated with your WABA are included.
[
"15550783881",
"15550783882",
"15550783883"
]
<PRICING_CATEGORIES>
Array of strings
Optional.
Array of pricing categories. If you send an empty array, we return results for all pricing categories.
Values can be:
AUTHENTICATION
: Messages charged the authentication rate.AUTHENTICATION_INTERATIONAL
: Messages charged the authentication-international rate.MARKETING
: Messages charged the marketing rate.SERVICE
: Messages that were not charged. Includes all non-template messages and utility messages sent inside of a customer service window.UTILITY
: Messages charged the utility rate. [
"AUTHENTICATION",
"MARKETING",
"UTILITY"
]
<PRICING_TYPES>
Array of strings
Optional.
Array of pricing types. If you send an empty array, we return results for all pricing types.
Values can be:
FREE_CUSTOMER_SERVICE
: Free messages. These are non-template messages and utility messages sent within customer service windows.FREE_ENTRY_POINT
: All messages sent within free entry point customer service windows.REGULAR
: Billable messages. Includes all authentication and marketing template messages, and any utility template messages sent outside of a customer service window. Excludes all messages sent within free entry point customer service windows. [
"REGULAR",
"FREE_CUSTOMER_SERVICE"
]
<START>
UNIX timestamp
Required.
UNIX timestamp indicating the start date for the date range you are retrieving analytics for.
1726014453
<WABA_ID>
String
Required.
WhatsApp Business Account ID.
102290129340398
Template analytics describe the number of times a template has been sent, delivered, and read, and the number of times URL buttons or Quick Reply buttons in the template have been clicked.
Data is returned with a daily granularity in the UTC timezone with a lookback of up to 90 days. Template analytics can also be found in the WhatsApp Manager> Message templates> Template details> Insightspanel.
MARKETING
or UTILITY
.To report template analytics bugs, submit a Direct Support ticket with the following selections:
You must confirm template analytics on your WhatsApp Business Account before you can get template analytics. You can confirm template analytics using the WhatsApp Manager or the API.
By confirming access via the API, you direct Meta to add insights to your WhatsApp Business Account. These insights include link tracking to report website clicks. You can turn off link tracking on each message template. You also direct Meta to collect and anonymize data from your chats with customers. Meta will anonymize this data to improve services it provides you and other businesses.
To confirm via API, send the following request:
POST /<WHATSAPP_BUSINESS_ACCOUNT_ID>?is_enabled_for_insights=true
Once confirmed, we will begin capturing template analytics for the WhatsApp Business Account. Once confirmed, template analytics cannot be disabled.
Upon success, the API will respond with your WhatsApp Business Account ID. For example:
{ "id": 102290129340398 }
start
UNIX Timestamp
Required.
The start timestamp for the date range you are retrieving analytics for. As template analytics are being provided with a daily granularity in the UTC timezone, a start timestamp other than 0:00 UTC would be corrected to its prior 0:00 UTC.
1543536000
end
UNIX Timestamp
Required.
The end date for the date range you are retrieving analytics for. As template analytics are being provided with a daily granularity in the UTC timezone, an end timestamp other than 0:00 UTC would be corrected to its next 0:00 UTC.
1543708800
granularity
Enum
Required.
The granularity by which you would like to retrieve the analytics. Value must be DAILY
.
DAILY
template_ids
Array of IDs
Required.
An array of template IDs for which you would like to retrieve analytics for.
Maximum 10.
[1924084211297547,954638012257287,969725530748535]
metric_types
Array of enums
Optional.
COST
node is NOT accessible to businesses who bill through a Solution Partner. To understand your charges, please reach out to your partner.
The types of metrics which you want to retrieve. If omitted or an empty array, analytics for all metric types will be returned.
Possible values:
COST
CLICKED
DELIVERED
READ
SENT
[SENT,DELIVERED,READ]
product_type
Enum
Optional.
The product type of the metrics you want to retrieve. If omitted, only analytics for Cloud API will be returned.
Possible values:
CLOUD_API
: Use this product type to filter for template metrics sent via Cloud APIMARKETING_MESSAGES_LITE_API
: Use this product type to filter for template metrics sent via Marketing Messages Lite API MARKETING_MESSAGES_LITE_API
Scenario:Given a 1-day timeframe, get all template analytics metric types for an authentication template and a marketing template with a URL button.
Example Request:
curl -g 'https://graph.facebook.com/ v21.0
/109259195336416/template_analytics?start=1718064000&end=1718122745&granularity=daily&metric_types=cost%2Cclicked%2Cdelivered%2Cread%2Csent&template_ids=[1421988012088524%2C2632273056924580]' \
-H 'Authorization: Bearer EAAJB...'
Example Response:
{ "data": [ { "granularity": "DAILY", "product_type": "cloud_api", // Only available to businesses in the Marketing Messages Lite API alpha "data_points": [ { "template_id": "1421988012088524", "start": 1718064000, "end": 1718150400, "sent": 1, "delivered": 1, "read": 1, "cost": [ { "type": "amount_spent", "value": 0.01 }, { "type": "cost_per_delivered", "value": 0.01 } ] }, { "template_id": "2632273056924580", "start": 1718064000, "end": 1718150400, "sent": 1, "delivered": 1, "read": 1, "clicked": [ { "type": "quick_reply_button", "button_content": "Contact Support", "count": 108 }, { "type": "unique_url_button", "button_content": "Tell me more", "count": 16 } ], "cost": [ { "type": "amount_spent", "value": 0.03 }, { "type": "cost_per_delivered", "value": 0.03 }, { "type": "cost_per_url_button_click", "value": 0.03 } ] } ] } ], "paging": { "cursors": { "before": "MAZDZD", "after": "MjQZD" } } }
Cost metricsare returned as an array of cost objects, each with a type and value. Types can be:
amount_spent
— Total amount spent on conversations opened within the start
and end
timeframe as a result of sending the template. See Opening Conversations
.cost_per_delivered
— The amount_spent
value divided by the number of times the template was delivered within the start
and end
timeframe.cost_per_url_button_click
— The amount_spent
value divided by the number of times the template's URL button was clicked, within the start
and end
timeframe. Quick reply button clicks are not included. Object omitted if the template does not have a URL button. Click metricsare returned as an array of JSON objects each with a type and value. Clicks are only returned for URL buttons and quick-reply buttons in templates categorized as MARKETING
or UTILITY
.
Types can be:
url_button
— The total number of clicks on the url button.unique_url_button
— Unique clicks track the number of distinct WhatsApp accounts that have clicked on a button. This metric helps you understand how many individual users are engaging with your CTAs, while eliminating duplicate clicks from the same recipient and providing an accurate measurement of engagement.You can disable button click tracking on an individual template by setting its cta_url_link_tracking_opted_out
field to true
. Once disabled, the API will no longer return the clicked property in template analytics or display button engagement/clicks in the WhatsApp Manager when viewing the template's insights.
POST /<TEMPLATE_ID> ?cta_url_link_tracking_opted_out=<OPT_OUT> &category=<TEMPLATE_CATEGORY>
Placeholder | Description | Example Value |
---|---|---|
Template ID |
Required. Template ID. |
|
Boolean |
Required. Indicates if template button click tracking is disabled. Set to This value is set to |
|
String |
Required. Template's current category. If you set the template category to a value other than its current category, the template status will be set to |
|
curl -X POST 'https://graph.facebook.com/ v21.0
/245435364965041?cta_url_link_tracking_opted_out=true&category=marketing' \
-H 'Authorization: Bearer EAAJB...'
Upon success, the API will respond with:
{ "success": true }
For a list of all possible values for each field, refer to the Graph API reference of the WhatsApp Business Account Analytics field .