AppTweak API - App Store Connect & Google Play Console data

Export App Store Connect and Google Play Console data by API

Carmen Longoby 
Former Junior Product Manager at AppTweak

9 min read

If you have been doing ASO for some time, you must be familiar with App Store Connect and Google Play Console. Both platforms offer the possibility to download some of the data they record about your app however they do it in very different ways.

On one hand, Apple allows you to quickly download any graph to a CSV which can be really nice when you want to share information with your team about a specific event. However, you don’t have the possibility to extract all of your “App Analytics” data at once if you want to include this data in your internal BI tool.

Google, on the other hand, has a whole section of its platform dedicated to exports but you can only download your acquisition reports by month which means that you might have to compile a bunch of CSV to be able to see your apps’ progression over the past year.

In the end, both of these solutions require a lot of manipulations before being able to import the exports into any BI tool. You end up spending more time formatting the data than actually analyzing it!

Many of our users flagged this pain point and asked us if AppTweak would be able to help. Today we are happy to announce that we have built a new API that allows AppTweak users to export their data from App Store Connect and Google Play Console.

Disclaimer : all of the numbers that you’ll see in this article are a randomized set of data that doesn’t belong to any app on the stores.


Integrate your ASO metrics with your own BI tools

To show you how this API will help you gain time we actually did the whole process ourselves. We took an app that had an App Store integration with AppTweak and extracted the data using AppTweak’s takeout API. We then turned the JSON file that was returned by the API into a CSV file and finally uploaded the file into Google Data Studio where we created a report of the app’s performance on the store.

Let’s take a closer look at the steps it takes to go from the API request to your app performance report.

Making calls to the API

Since the takeout API is designed to allow you to fetch information about your account, you need to use the API token associated with your AppTweak account. This API token can be found in the “General Info” tab of your account.

API app report - apptweak aso tool

In the documentation, you’ll find all the information to help you write the API calls. At the moment, there are 7 different endpoints that can be called using your API token :

GET /takeout/integrations

This endpoint allows you to get the “api_account_ids” that are linked to your store integrations. This id will allow you to later fetch the data for your App Store Connect or Google Play Store account.

For Apple & Google Play, you can fetch your data in two ways :

GET /takeout/integrations/${API_ACCOUNT_ID}/reports/${PROPERTY}.json

The first one allows you to fetch the data by country. You just need to specify the api_account_id and the property that you want to look at (eg. app units, page views…) in the request.

GET /takeout/integrations/{API_ACCOUNT_ID}/reports/acquisition-channel.json

The second one allows you to fetch the data by acquisition channel. Again you’ll need to specify the api_account_id, however all metrics are returned in the response.

GET /takeout/integrations/{API_ACCOUNT_ID}/reports/acquisition-keywords-monthly.json

This request will return the keywords that drive the most installs to your android app (Google Play Install Keywords) each month and the amount of installers, store listing visitors and retained installers that the keyword brought.

GET /takeout/integrations/{API_ACCOUNT_ID}/reports/acquisition-keywords-aggregate.json

This request is very similar to the previous one except for the fact that you can specify the period over which you wish to see the keywords and compute the installers, store listing visitors and retained installers data.

For all these requests you can also specify a set of parameters to help you narrow down the data that you want to fetch. Among those you’ll have :

  • products : the ids of the apps
  • countries : the country codes of the countries
  • start_date & end_date : the selected time period
  • devices : for ios only, iphone, ipad, both

For our example, we wrote the following method in Ruby to fetch the “App Analytics” data from App Store Connect.

# TAKEOUT iTunes Connect by channel (GET )
def send_request(api_account_id,countries,products,devices,start_date,end_date)
 uri = URI("https://app.apptweak.com:443/takeout/integrations/#{api_account_id}/reports/acquisition-channel.json?countries=#{countries}&products=#{products}&devices=#{devices}&start_date=#{start_date}&end_date=#{end_date}")

 # Create client
 http = Net::HTTP.new(uri.host, uri.port)
 http.use_ssl = true
 http.verify_mode = OpenSSL::SSL::VERIFY_PEER

 # Create Request
 req =  Net::HTTP::Get.new(uri)
 # Add headers
 req.add_field "X-AppTweak-Key", "add you API key here"

 # Fetch Request
 res = http.request(req)
 puts "Response HTTP Status Code: #{res.code}"
 puts "Response HTTP Response Body: #{res.body}"
 res.body
rescue StandardError => e
 puts "HTTP Request failed (#{e.message})"
end

Now that we have managed to make a successful call to the API we will look at the response.

The API responses are all in JSON. Basically, the JSON document is a hash which contains the response content and metadata about the request and about the response itself.

For the example above, this is the response we got :

{"content":{
   "123455748":{
       "CA":{
           "search":{
               "start_date":"2020-03-01",
               "end_date":"2020-03-07",
               "impressions_total_unique":[524.0,455.0,435.0,458.0,453.0,415.0,524.0],
               "page_view_unique":[22.0,28.0,22.0,22.0,24.0,20.0,24.0],
               "units":[52.0,24.0,22.0,25.0,33.0,27.0,35.0]},
           "other":{
               "start_date":"2020-03-01",
               "end_date":"2020-03-07",
               "impressions_total_unique":[22545.0,8457.0,8543.0,20534.0,22025.0,22434.0,22847.0],
               "page_view_unique":[2583.0,2283.0,2233.0,2238.0,2232.0,2320.0,2438.0],
               "units":[75.0,54.0,52.0,72.0,55.0,45.0,74.0]},
           "appref":{
               "start_date":"2020-03-01",
               "end_date":"2020-03-07",
               "impressions_total_unique":[4372.0,3707.0,3788.0,3744.0,3588.0,4203.0,5555.0],
               "page_view_unique":[4372.0,3707.0,3788.0,3744.0,3588.0,4203.0,5555.0],
               "units":[40.0,48.0,50.0,52.0,52.0,44.0,52.0]},
           "webref":{
               "start_date":"2020-03-01",
               "end_date":"2020-03-07",
               "impressions_total_unique":[4822.0,4034.0,3853.0,3422.0,3854.0,4275.0,5820.0],
               "page_view_unique":[4822.0,4034.0,3853.0,3422.0,3854.0,4275.0,5820.0],
               "units":[202.0,74.0,42.0,77.0,45.0,74.0,232.0]},
           "unknown":{
               "start_date":"2020-03-01",
               "end_date":"2020-03-07",
               "impressions_total_unique":[0.0,0.0,0.0,0.0,0.0,0.0,0.0],
               "page_view_unique":[0.0,0.0,0.0,0.0,0.0,0.0,0.0],
               "units":[2.0,2.0,2.0,2.0,0.0,2.0,2.0]}}},
"metadata":{
   "request":{
       "path":"/accounts/12ab34c5-6d78-9e10-fgh/reports/acquisition-channel.json",
       "params":{
           "countries":"ca",
           "devices":"iphone",
           "end_date":"2020-03-07T00:00:00+00:00",
           "products":"123456789",
           "start_date":"2020-03-01T00:00:00+00:00",
           "id":"12ab34c5-6d78-9e10-fgh",
           "property":"acquisition-channel",
           "format":"json"},
           "performed_at":"2020-03-13 14:00:12 UTC"},
           "content":{}}}

From JSON to CSV

As you can see the response is already well structured however it is still not compatible with all BI tools, therefore we will need to convert this JSON into a CSV file.

Again for this example, we wrote a short script in Ruby that takes the elements of the response above and structures them using nested loops to build a set of arrays that are actually the entries of our worksheet.

def parse_json(response)
   hash = JSON.parse(response)
   response_hash = {}
   hash["content"].each do |app_id, country_hash|
       response_hash[app_id] ||= {}
       country_hash.each do |country, channel_hash|
           response_hash[app_id][country] ||= {}
           channel_hash.each do |channel, data_hash|
               start_date = Date.parse(data_hash["start_date"])
               data_hash["impressions_total_unique"].each_with_index do |val, index|
                   current_date = start_date + index
                   response_hash[app_id][country][current_date] ||= [app_id, country, current_date]
                   response_hash[app_id][country][current_date] << val
               end
               data_hash["page_view_unique"].each_with_index do |val, index|
                   current_date = start_date + index
                   response_hash[app_id][country][current_date] << val
               end
               data_hash["units"].each_with_index do |val, index|
                   current_date = start_date + index
                   response_hash[app_id][country][current_date] << val
               end
           end
       end
   end
   response_hash
end


CSV.open("takeout-ios.csv", "a+") do |csv|
   csv << ["App ID", "Country", "Date",
   "App Units - App Store Search", "Product Page Views - App Store Search", "Impressions - App Store Search",
   "App Units - App Store Browse", "Product Page Views - App Store Browse", "Impressions - App Store Browse",
   "App Units - App Referrer", "Product Page Views - App Referrer", "Impressions - App Referrer",
   "App Units - Web Referrer", "Product Page Views - Web Referrer", "Impressions - Web Referrer",
   "App Units - Unavailable", "Product Page Views - Unavailable", "Impressions - Unavailable"]

   api_account_id = "12ab34c5-6d78-9e10-fgh"
   products = "123456789"
   devices = "iphone"
   countries = "ca"
   start_date ="2020-03-01"
   end_date = "2020-03-07"

   response = send_request(api_account_id,countries,products,devices,start_date,end_date)
   itunes_data = parse_json(response)
   itunes_data.each do |_app_id, country_array|
       country_array.each do |_country, date_array|
           date_array.each do |_date, row|
               csv << row
           end
       end
   end
end

This script will generate a file called takeout-ios.csv where I’ll find my app’s app units, page views and impressions spread by source (iPhone only, Canada).

API app report - apptweak aso tool

From CSV to your report

Now that we have managed to generate the CSV with the raw data, the next step is to upload this file in a BI tool. For this example we decided to use Google Data Studio but you can also do this process with Tableau, QuikView, PowerBI or any other data visualization tool.

API app report - apptweak aso tool

In a couple of seconds the file is uploaded. If needed we can now add additional fields. For example, we can add new fields for Total Units, Total Product Page View and Total Impressions which are basically the sum of all sources.

API app report - apptweak aso tool

Once this is done we can start creating the charts and tables that we want to see in the report or we can upload this data to an existing report.

API app report - apptweak aso tool

And there it is, we managed to build a great report of your App Analytics data from App Store Connect! While this process might seem complicated at first, but once it’s been done it will save precious time for when you want to update the report again.

I hope you enjoyed this blog and will implement a system like this one to export your data from AppTweak!

Start a 7-day free trial

Carmen Longo
by , Former Junior Product Manager at AppTweak
Carmen is a former Senior Product Manager at AppTweak. Her expertise in ASO helps her to continuously improve and build disruptive features. Like most “Apptweakers”, her life revolves around food.