Retrieving ads metrics per campaign


I’m using the twitter-ads python library and trying to fetch some ads metrics with it (within a date range), without success.

I’m trying first with this entrypoint/ params:

resource = '/4/stats/accounts/{account_id}/'.format(
params = {'entity': 'CAMPAIGN',
          'entity_ids': 'xxxx,xxxx',
          'start_time': '2018-10-03',
          'end_time': '2018-10-10',
          'granularity': 'DAY',
          'metric_groups': 'ENGAGEMENT,MEDIA,WEB_CONVERSION',
          'placement': 'PUBLISHER_NETWORK'}

However I’m not getting data at the ads level, just campaign details.
What I need is to retrieve a list of ads by campaign with the stats, conversion, engagement, etc, as we can see in the web interface.

If I want to retrieve line_items data it forces me to pass the line_items_ids as a parameter which I don’t have.

What’s the right way to approach this?

Thanks in advance


Thanks for the question, @Outflink. What is the account ID? What campaign IDs are you requesting data for? Please see our Guideline for Reporting Issues.


@juanshishido Thanks for your answer.

Actually, the problem is not with a specific account_id or campaign_id. What we need is to retrieve data for any of the accounts / campaigns we are managing.

Let me explain:

We are trying to fetch metrics / stats per date for each one of the promoted tweets on the accounts and campaigns we’re running.

This is how we are trying to do it:

  1. We fetch all the promoted tweets per account
  2. Then we fetch metrics for every one of them (20 per call as per the docs)

Even though it seems to work we found this process very expensive.

So the rephrased question would be: Is there a way to retrieve the metrics / stats per day for all the ads / promoted tweets on a campaign or account in one REST call? Or the way we’ve found is the right one?



I need to look into the specifics of campaign you’re fetching data for to answer the following.

In terms of your new / rephrased question, there is not a way to fetch what you’re looking for in a single request. In addition, fetching data for every promoted_tweets entity may not be the best approach. It’s likely that not every ad is in flight for the days you’re fetching data for. That means there are likely wasted calls—i.e., calls that did not need to be made since there is no data for the specified time period.

You also said you don’t have line item IDs. Why not? You can page through the GET accounts/:account_id/line_items endpoint.


It’s likely that not every ad is in flight for the days you’re fetching data for. That means there are likely wasted calls—i.e., calls that did not need to be made since there is no data for the specified time period.

Exactly, that’s my concern, I wonder if there is a better approach for requesting the data I need.
And basically what I need is all stats/ metrics for all the ads (promoted tweets) between two dates.

About the line_items you’re right, the same way I get the promoted tweets I can get the line items ids however I’d be facing the same issue about the unnecessary calls.

So It seems I have no chance but to retrieve all the promoted tweets ids and then query for metrics over all of them even though there might be some of them without data?

Btw, could you please explain what’s the exact difference between a line_item and a promoted_tweet? I’ve seen the same tweet ID in more than a line_item and yet I don’t understand what’s the line item use case.

Appreciate your help, thank you!


If I want to get data at the ads level, each add with its metrics per day, what’s the entity I should ask for? line_item or promoted_tweet?



I’ve have an specific example of a promoted tweet who has some impressions as I can see in the ads manager, but when retrieving its metrics through the API I get everything None/ null.

promoted_tweet_id: 2a6f9x
tweet id: 1048974475667025925
line_item id: clsfq
between 2018-10-08 and 2018-10-09

In the ads manager I see 160 impressions for the 3 days, (2, 147, 11).
However in the data coming from the API this is the result:

[{'id': '2a6f9x',
  'id_data': [{'metrics': {'app_clicks': None,
                           'auto_created_conversion_add_to_cart': None,
                           'auto_created_conversion_add_to_wish_list': None,
                           'auto_created_conversion_added_payment_info': None,
                           'auto_created_conversion_checkout_initiated': None,
                           'auto_created_conversion_complete_registration': None,
                           'auto_created_conversion_content_view': None,
                           'auto_created_conversion_download': None,
                           'auto_created_conversion_page_view': None,
                           'auto_created_conversion_purchase': None,
                           'auto_created_conversion_search': None,
                           'auto_created_conversion_sign_up_initiated': None,
                           'card_engagements': None,
                           'carousel_swipes': None,
                           'clicks': None,
                           'conversion_custom': {'metric': None,
                                                 'order_quantity': None,
                                                 'order_quantity_engagement': None,
                                                 'order_quantity_view': None,
                                                 'post_engagement': None,
                                                 'post_view': None,
                                                 'sale_amount': None,
                                                 'sale_amount_engagement': None,
                                                 'sale_amount_view': None},
                           'conversion_downloads': {'metric': None,
                                                    'order_quantity': None,
                                                    'order_quantity_engagement': None,
                                                    'order_quantity_view': None,
                                                    'post_engagement': None,
                                                    'post_view': None,
                                                    'sale_amount': None,
                                                    'sale_amount_engagement': None,
                                                    'sale_amount_view': None},
                           'conversion_purchases': {'assisted': None,
                                                    'metric': None,
                                                    'order_quantity': None,
                                                    'order_quantity_engagement': None,
                                                    'order_quantity_view': None,
                                                    'post_engagement': None,
                                                    'post_view': None,
                                                    'sale_amount': None,
                                                    'sale_amount_engagement': None,
                                                    'sale_amount_view': None},
                           'conversion_sign_ups': {'assisted': None,
                                                   'metric': None,
                                                   'order_quantity': None,
                                                   'order_quantity_engagement': None,
                                                   'order_quantity_view': None,
                                                   'post_engagement': None,
                                                   'post_view': None,
                                                   'sale_amount': None,
                                                   'sale_amount_engagement': None,
                                                   'sale_amount_view': None},
                           'conversion_site_visits': {'metric': None,
                                                      'order_quantity': None,
                                                      'order_quantity_engagement': None,
                                                      'order_quantity_view': None,
                                                      'post_engagement': None,
                                                      'post_view': None,
                                                      'sale_amount': None,
                                                      'sale_amount_engagement': None,
                                                      'sale_amount_view': None},
                           'engagements': None,
                           'follows': None,
                           'impressions': None,
                           'likes': None,
                           'media_engagements': None,
                           'media_views': None,
                           'poll_card_vote': None,
                           'qualified_impressions': None,
                           'replies': None,
                           'retweets': None,
                           'tweets_send': None,
                           'unfollows': None,
                           'url_clicks': None},
               'segment': None}]}]

This is my request:

URI: '/4/stats/accounts/18ce54lpp19
params = {
        'entity': 'PROMOTED_TWEET',
        'entity_ids': '2a6f9x',
        'start_time': '2018-10-07',
        'end_time': '2018-10-09',
        'granularity': 'DAY',
        'metric_groups': 'ENGAGEMENT,MEDIA,WEB_CONVERSION',
        'placement': 'PUBLISHER_NETWORK'}

Any idea of where could be the issue?


+1. I have the same ask.

From my understanding, line item refers to the ad groups so promoted tweets would be a part of an ad group.

I could define account, campaign and line item but did not get the method to define the promoted tweet or how to get a list of promoted tweets from a campaign or line item

account = client.accounts(ACCOUNT_ID)
campaign = account.campaigns().next()
line_item = account.line_items(None,
promoted_tweet = ???

What would be the code in this case to do the following:

  • Get the list of promoted tweets in a line item or campaign or account

  • Make a call to get metrics for a list of promoted tweets


Could you please share the code for how you are getting the id for promoted tweets. I am able to get the metrics by campaign and line item level but not get the list of promoted tweets.

I used a nested loop to drill down to the list of line items.

for campaign in account.campaigns():
    if 'XXXXXX' in #or whatever classification method you use in your campaigns
        cidlist.extend([]) #creates a list of campaign ids
        for line_item in account.line_items(
            lidlist.extend([]) #creates a list of line item ids
mynewlist = list(set(lidlist))


This would be the promoted tweets. Line items in our case refer to audience segments


Here is you code. Thanks to @juanshishido for the help.

account = client.accounts(ACCOUNT_ID)
campaign = account.campaigns().next()
line_item = account.line_items(None,
promoted_tweet = PromotedTweet.all(account,

ptidlist = []

#perhaps not the most computing optimal method but suggestions on how to rework this are welcome
for campaign in account.campaigns():
    if 'XXXXXX' in
        for line_item in account.line_items(
            for promoted_tweet in PromotedTweet.all(account,

for i in ptidlist:          
    resource = '/4/stats/accounts/{account_id}/'.format(
    params = { 'entity':'PROMOTED_TWEET', #this is where promoted tweet ids will go
    'entity_ids': i,#this is where promoted tweet ids will go
    'start_time': '2018-09-30',
    'metric_groups': ['BILLING'],
    'placement': 'ALL_ON_TWITTER'}
    response = Request(client, 'get', resource, params=params).perform()

Good luck!


Does promoted tweet stats give the stats for both organic tweets that were promoted after publishing and for promoted only tweets (dark posts) ?


Hey thanks for your help
I agree with you, it’s not the most optimal way but I haven’t found any other way.

In any case as I said before, I see null data coming for ids that have some numbers in the ads manager interface,… @juanshishido could you please have a look at those ids?

Appreciate your help guys,


Try changing the granularity to Day and then comparing it to the report for day to day performance in ads manager


@WestDigi That’s exactly how I do the request, by DAY granularity.
Btw you don’t need to make a call for every tweet, you can pass a list of 20 promoted tweets ids per request.

@juanshishido another issue I see is that I query analytics data between ‘2018-10-07’ and ‘2018-10-08’ for a specific campaign, and one of the tweets I get metrics for (which is promoted_tweet_id: “29mf0z”. However if I go to the twitter ads manager in the UI I filter by those dates, same campaign I don’t see its corresponding tweet_id in the list.

@juanshishido I’d really appreciate your help

Thanks a lot,


Also in the results ,when metric value comes as an object, it has this fields:
post_view, order_quantity, assisted, post_engagement, sale_amount…

Could you explain what’s the difference between them?

Thanks in advance


A line item is the entity under a campaign and is where the bid, objective, placement, etc. are set. A promoted_tweets entity is the association between a Tweet—something a user would see on Twitter—and the line item. It’s how you’d specify which Tweet to promote.

If you see the same Tweet ID associated with multiple line items it means they are being promoted in the campaigns associated with those line items. There is no restriction about how many campaigns a Tweet can be promoted in. Why would you want to do this? Well, perhaps one line item might be targeting a specific set of users or have a different bid or, if part of a different campaign, can have a different objective.

For the ad-level, you would request stats as follows: entity=PROMOTED_TWEET and specify the IDs you’re interested in.

Note that I am:

  • Looking at October 7th through the 9th, inclusive. Three total days.
  • Looking at promoted_tweets ID 2a6f9x.
  • I am using TOTAL granularity (for convenience).

In Ads Manager, I am seeing 165 total impressions for this entity. I see the same through the Ads API.

$ twurl -H "/4/stats/accounts/18ce54lpp19?entity=PROMOTED_TWEET&entity_ids=2a6f9x&start_time=2018-10-07&end_time=2018-10-10&granularity=TOTAL&metric_groups=ENGAGEMENT&placement=ALL_ON_TWITTER"
  "data_type": "stats",
  "time_series_length": 1,
  "data": [
      "id": "2a6f9x",
      "id_data": [
          "segment": null,
          "metrics": {
            "impressions": [
            "tweets_send": null,
            "qualified_impressions": null,
            "follows": null,
            "app_clicks": null,
            "retweets": null,
            "unfollows": null,
            "likes": null,
            "engagements": [
            "clicks": [
            "card_engagements": null,
            "poll_card_vote": null,
            "replies": null,
            "url_clicks": null,
            "carousel_swipes": null
  "request": {
    "params": {
      "start_time": "2018-10-06T23:00:00Z",
      "segmentation_type": null,
      "entity_ids": [
      "end_time": "2018-10-09T23:00:00Z",
      "country": null,
      "placement": "ALL_ON_TWITTER",
      "granularity": "TOTAL",
      "entity": "PROMOTED_TWEET",
      "platform": null,
      "metric_groups": [

Notice that I am requesting placement=ALL_ON_TWITTER. The other important thing to notice is the date range I’ve specified: end_time=2018-10-10. This is because the end date is exclusive in the Ads API. When you omit the timestamp, we assume midnight in the account’s timezone. As an example, if you say 2018-01-01 to 2018-01-02—recalling that both are at midnight—you will only get one day’s worth of data.

I think this should answer all of your questions, @Outflink. Thanks again for the detailed explanations.


@juanshishido Thanks for your answer, that was helpful!

However we are still seeing discrepancies between data from the ads manager interface and data we bring from the API.

We are comparing a ads report for the 10th of november 2018.

Granularity: DAY.

In the ads manager we get 19,353 impressions.
From the API we get 17558 impresions.

Same campagin, same date, same amount and names of ad groups -but- different numbers.

The report is for all the ads so in our script we get all the promoted tweets ids for the campaign and we make the amount of requests needed to fetch their stats (until 20 entity ids per request as documented).

This is how our requests look like:

resource = '/4/stats/accounts/{account_id}'.format(

        params = {
            'entity': 'PROMOTED_TWEET',
            'entity_ids': '29mf10,29mf11,29mf12,29mf13,29mf14,2a6fk0,2a6fk1,2a6fk2,2a6fk3,2a6fk4,2a6fk5,2a6fk6,2a6fk7,2a6fk8,2a6fk9,2a6fka,2a6fkb,2a6fkc,2a6fkd,2a6fke',
            'start_time': '2018-11-10',
            'end_time': '2018-11-11',
            'granularity': 'DAY',
            'placement': 'ALL_ON_TWITTER'}

However there is another campaign (PS-UK-DIS-BRANDVOD-GVOD-TSG-TWITTER-TWITTER-ROS-M1834-ALL-Q4AB2WAT-NO-AS-VidPromoted-P-HandlesKW) on which the numbers match perfectly.

What are we doing wrong?

Thanks in advance,



Are you checking both placements? Are you sure you have all promoted_tweets (even deleted ones)?

Finally, what is the campaign objective?