Use amCharts 4 to visualize Google Analytics data

Intro

Google exposes data from its Analytics service using a number of various APIs.

NOTE: you can download the files created in this tutorial using link at the bottom.

Setting up Google Analytics API

Before you can extract data from your Analytics account, you will need to set up an application and API access to it.

Since our main aim is to display Analytics data to users who don’t necessarily have access to our GA accounts, we’ll need the server-to-server authentication and a server-side script to act as a proxy between the user and Google API.

To use that you’ll need to set up a “Service account” in your Google Console.

Follow this excellent tutorial to do so:

Hello Analytics API: PHP quickstart for service accounts

Creating a GA service account
Creating a GA service account

Once you create the Service account, you’ll be offered to save a P12 file. Do it. You’ll need it to authenticate your PHP script’s access to Analytics.

Also note the Email address auto-generated for your application. You’ll need it to set up authentication as well.

Service account information
Service account information

Using PHP to extract Google Analytics data

Prerequisites

Google has provided a PHP library to access their API services. Download or better yet check it out directly from their GitHub repository:

https://github.com/google/google-api-php-client

We’ll also be using slightly modified version of the sample PHP script shown in this Google tutorial:

Hello Analytics API: PHP quickstart for service accounts

Authorizing

As mentioned earlier, you’ll need three things to authorize your PHP script for access to your Analytics data:

  • Service account email
  • Authorization file
  • Analytics profile ID

We took the code from Google tutorial and modified it to be slightly more universal:

<?php
/**
 * Load Google API library
 */
require_once 'google-api-php-client/src/Google/autoload.php';

/**
 * Start session to store auth data
 */
session_start();

/**
 * Set Google service account details
 */
$google_account = array(
  'email'   => '********@developer.gserviceaccount.com',
  'key'     => file_get_contents( '********.p12' ),
  'profile' => '85639843'
);

/**
 * Get Analytics API object
 */
function getService( $service_account_email, $key ) {
  // Creates and returns the Analytics service object.

  // Load the Google API PHP Client Library.
  require_once 'google-api-php-client/src/Google/autoload.php';

  // Create and configure a new client object.
  $client = new Google_Client();
  $client->setApplicationName( 'Google Analytics Dashboard' );
  $analytics = new Google_Service_Analytics( $client );

  // Read the generated client_secrets.p12 key.
  $cred = new Google_Auth_AssertionCredentials(
      $service_account_email,
      array( Google_Service_Analytics::ANALYTICS_READONLY ),
      $key
  );
  $client->setAssertionCredentials( $cred );
  if( $client->getAuth()->isAccessTokenExpired() ) {
    $client->getAuth()->refreshTokenWithAssertion( $cred );
  }

  return $analytics;
}

/**
 * Get Analytics API instance
 */
$analytics = getService(
  $google_account[ 'email' ],
  $google_account[ 'key' ]
);

/**
 * Query the Analytics data
 */
$results = $analytics->data_ga->get(
  'ga:' . $google_account[ 'profile' ],
  '30daysAgo',
  'today',
  'ga:sessions',
  array(
    'dimensions'  => 'ga:country',
    'sort'        => '-ga:sessions',
    'max-results' => 20
  ) );
$rows = $results->getRows();
var_dump($rows);

When you run this file, if you have correctly configured your Google API credentials, added Service account email to your Analytics properties, you should see the PHP script print out the number of sessions your web property received in the past 7 days.

array (size=1)
  0 =>
    array (size=1)
      0 => string '7279' (length=4)

Authorization works!

Querying the data

Data from Analytics is extracted using “queries”. In the previous example we used query “ga:sessions” to extract a single number of visitor sessions.

Now let’s do something more interesting. Let’s extract number of sessions from the last 30 days per country.

We’ll replace our query’s start date to “30daysAgo”.

Will leave metric at “ga:sessions”.

We’ll also add additional parameters: dimension (country), sort order, and number of results to return.

$results = $analytics->data_ga->get(
  'ga:' . $profile,
  '30daysAgo',
  'today',
  'ga:sessions',
  array(
    'dimensions'  => 'ga:country',
    'sort'        => '-ga:sessions',
    'max-results' => 10
  ) );
$rows = $results->getRows();
var_dump($rows);

You’ll notice we have introduced the 5th parameter to the get() method call, which is an associative array of optional parameters.

The Google Analytics parameter value usually is prefixed with a “ga:” prefix.

The minus sign in front of “ga:sessions” means I want it to order in ascending order.

Now, when you run the above, you’ll get something like this:

array (size=10)
  0 =>
    array (size=2)
      0 => string 'United States' (length=13)
      1 => string '4858' (length=4)
  1 =>
    array (size=2)
      0 => string 'India' (length=5)
      1 => string '4020' (length=4)
  2 =>
    array (size=2)
      0 => string 'France' (length=6)
      1 => string '1305' (length=4)
  3 =>
    array (size=2)
      0 => string 'Russia' (length=6)
      1 => string '1203' (length=4)
  4 =>
    array (size=2)
      0 => string 'China' (length=5)
      1 => string '1170' (length=4)
...

Neat, huh?

Using Query Explorer to construct and test API queries

Google has provided a powerful tool, that you can use to construct and test API queries, called Query Explorer.

As a side effect of using Query Explorer you can also find out the profile ID of your Analytics property.

Charting extracted data

Now that we have the data, we can go about plotting it with the chart.

Formatting data in JSON

While the data we extracted (session per country) might look OKish on screen, it can’t be used directly by chart. Let’s re-format it to JSON - a format much more suitable for charts.

/**
 * Format and output data as JSON
 */
$data = array();
foreach( $rows as $row ) {
  $data[] = array(
    'country'   => $row[0],
    'sessions'  => $row[1]
  );
}

echo json_encode( $data );

Now that produces a perfect and valid, object-oriented JSON:

[ {
  "country": "United States",
  "sessions": "4867"
}, {
  "country": "India",
  "sessions": "4029"
}, {
  "country": "France",
  "sessions": "1311"
}, {
  "country": "Russia",
  "sessions": "1203"
}, {
  "country": "China",
  "sessions": "1171"
}, {
  "country": "Germany",
  "sessions": "1151"
}, {
  "country": "South Korea",
  "sessions": "1096"
}, {
  "country": "United Kingdom",
  "sessions": "1087"
}, {
  "country": "Japan",
  "sessions": "1064"
}, {
  "country": "Brazil",
  "sessions": "931"
} ]

We’re done with the data.php file for now.

Using the data in chart

We’re going to use amChart’s plugin Data Loader, to automatically load external data:

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <title>amCharts - Google Analytics example</title>
    <script src="https://www.amcharts.com/lib/4/core.js"></script>
    <script src="https://www.amcharts.com/lib/4/charts.js"></script>
    <style>
    body, html {
      font-size: 12px;
    }
    #chartdiv {
      width: 100%;
      height: 400px;
    }
    </style>
    <script>
    // Create chart instance
    var chart = am4core.create("chartdiv", am4charts.XYChart);

    // Load data
    chart.dataSource.url = "data.php";

    // Create axes
    var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
    categoryAxis.dataFields.category = "country";
    categoryAxis.renderer.grid.template.location = 0;
    categoryAxis.renderer.minGridDistance = 30;
    categoryAxis.title.text = "Country";
    categoryAxis.title.fontWeight = "bold";

    var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
    valueAxis.title.text = "Sessions";
    valueAxis.title.fontWeight = "bold";

    // Create series
    var series = chart.series.push(new am4charts.ColumnSeries());
    series.dataFields.valueY = "sessions";
    series.dataFields.categoryX = "country";
    series.name = "Sessions";
    </script>
  </head>

  <body>
    <div id="chartdiv"></div>
  </body>

</html>

This produces a nice result:

A chart generated from GA data

Combining multiple metrics in a single query

Let’s say you want to display a number of metrics in the same dashboard. For example, along sessions you could want to plot number of unique users and page views as well. Naturally, it would be very inefficient to create separate queries for each of those metrics.

Luckily, Analytics API allows to specify several metrics in the same request. You just need to separate them by comma:

/**
 * Query the Analytics data
 */
$results = $analytics->data_ga->get(
  'ga:' . $google_account[ 'profile' ],
  '30daysAgo',
  'today',
  'ga:sessions,ga:users,ga:pageviews',
  array(
    'dimensions'  => 'ga:country',
    'sort'        => '-ga:sessions',
    'max-results' => 10
  ) );
$rows = $results->getRows();

/**
 * Format and output data as JSON
 */
$data = array();
foreach( $rows as $row ) {
  $data[] = array(
    'country'   => $row[0],
    'sessions'  => $row[1],
    'users'     => $row[2],
    'pageviews' => $row[3]
  );
}

echo json_encode( $data );

Now let’s update our chart code to display all that new data:

// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);

// Load data
chart.dataSource.url = "data.php";

// Create axes
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "country";
categoryAxis.renderer.grid.template.location = 0;
categoryAxis.renderer.minGridDistance = 30;
categoryAxis.title.text = "Country";
categoryAxis.title.fontWeight = "bold";

var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.title.text = "Users/Sessions";
valueAxis.title.fontWeight = "bold";
var valueAxis2 = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis2.title.text = "Pageviews";
valueAxis2.title.fontWeight = "bold";
valueAxis2.renderer.opposite = true;
valueAxis2.renderer.grid.template.disabled = true;

// Create series
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.valueY = "sessions";
series.dataFields.categoryX = "country";
series.name = "Sessions";

var series2 = chart.series.push(new am4charts.ColumnSeries());
series2.dataFields.valueY = "users";
series2.dataFields.categoryX = "country";
series2.name = "Users";

var series3 = chart.series.push(new am4charts.LineSeries());
series3.dataFields.valueY = "pageviews";
series3.dataFields.categoryX = "country";
series3.name = "Pageviews";
series3.strokeWidth = 3;
series3.yAxis = valueAxis2;

var bullet3 = series3.bullets.push(new am4charts.CircleBullet());
bullet3.circle.radius = 5;
bullet3.circle.stroke = am4core.color("#fff");
bullet3.circle.strokeWidth = 2;

// Add legend
chart.legend = new am4charts.Legend();

And voila:

Combined data from GA using single query

Files used in this article

Download the final files of the files produced in this article:
amcharts4_google_analytics_files.zip