++ed by:

1 non-PAUSE user.

Jan Henning Thorsen


Mojo::GoogleAnalytics - Extract data from Google Analytics using Mojo UserAgent


  my $ga     = Mojo::GoogleAnalytics->new("/path/to/credentials.json");
  my $report = $ga->batch_get({
    viewId     => "ga:123456789",
    dateRanges => [{startDate => "7daysAgo", endDate => "1daysAgo"}],
    dimensions => [{name => "ga:country"}, {name => "ga:browser"}],
    metrics    => [{expression => "ga:pageviews"}, {expression => "ga:sessions"}],
    orderBys   => [{fieldName => "ga:pageviews", sortOrder => "DESCENDING"}],
    pageSize   => 10,

  print $report->rows_to_table(as => "text");


Mojo::GoogleAnalytics is a Google Analytics client which allow you to extract data non-blocking.

This module is work in progress and currently EXPERIMENTAL. Let me know if you start using it or has any feedback regarding the API.



  $hash_ref = $self->authorization;

Holds authorization data, extracted by "authorize". This can be useful to set from a cache if Mojo::GoogleAnalytics objects are created and destroyed frequently, but with the same credentials.


  $str = $self->client_email;

Example: "some-app@some-project.iam.gserviceaccount.com".


  $str = $self->client_id;

Example: "103742165385019792511".


  $str = $self->private_key;

Holds the content of a pem file that looks like this:

  -----END PRIVATE KEY-----


  $ua = $self->ua;
  $self = $self->ua(Mojo::UserAgent->new);

Holds a Mojo::UserAgent object.


  $str = $self->view_id;
  $self = $self->view_id("ga:123456789");

Default viewId, used by "get_report".



  $self = $self->authorize;
  $self = $self->authorize(sub { my ($self, $err) = @_; });

This method will set "authorization". Note that this method is automatically called from inside of "batch_get", unless already authorized.


  $promise = $self->authorize_p;

Same as "authorize", but returns a Mojo::Promise.


  $report = $self->batch_get(\%query);
  $self = $self->batch_get(\%query, sub { my ($self, $err, $report) = @_ });

Used to extract data from Google Analytics. $report will be a Mojo::Collection if $query is an array ref, and a single Mojo::GoogleAnalytics::Report object if $query is a hash.

$err is a string on error and false value on success.


  $promise = $self->batch_get_p(\%query);

Same as "batch_get", but returns a Mojo::Promise.


  $self = $self->from_file("/path/to/credentials.json");

Used to load attributes from a JSON credentials file, generated from https://console.developers.google.com/apis/credentials. Example file:

    "type": "service_account",
    "project_id": "cool-project-238176",
    "private_key_id": "01234abc6780dc2a3284851423099daaad8cff92",
    "private_key": "-----BEGIN PRIVATE KEY-----...\n-----END PRIVATE KEY-----\n",
    "client_email": "some-name@cool-project-238176.iam.gserviceaccount.com",
    "client_id": "103742165385019792511",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://accounts.google.com/o/oauth2/token",

Note: The JSON credentials file will probably contain more fields than is listed above.


  $report = $self->get_report(\%query);
  $self = $self->get_report(\%query, sub { my ($self, $err, $report) = @_ });

This method is the same as "batch_get", but will do some translations on the input queries before passing it on to "batch_get". Example:

    dimensions => "ga:productName",
    metrics    => "ga:productListClicks,ga:productListViews",
    interval   => [qw(7daysAgo 1daysAgo)],
    order_by   => ["ga:productListClicks desc"],
    filters    => [ ["ga:currencyCode" => "eq" => ["USD"]] ],
  • dimensions

    dimensions will be translated from a comma separated string, or passed on directly to Google Analytics if not. The example above results in this query:

      dimensions => [{name => "ga:productName"}]
  • filters

    filters is a simpler version of dimensionFilterClauses and metricFilterClauses. The format is:

      filters => [ [$fieldName, $operator, $value] ]

    The $operator will be used to determine if the expression should go into dimensionFilterClauses or metricFilterClauses.

      Input operator | Filter group          | Analytics operator
      eq             | dimensionFilterClause | EXACT
      ^              | dimensionFilterClause | BEGINS_WITH
      $              | dimensionFilterClause | ENDS_WITH
      =~             | dimensionFilterClause | REGEXP
      substr         | dimensionFilterClause | PARTIAL
      ==             | metricFilterClause    | EQUAL
      >              | metricFilterClause    | GREATER_THAN
      <              | metricFilterClause    | LESS_THAN

    The filter will be "NOT" if the operator is prefixed with "!".

  • interval

    interval can be used as a simpler version of dateRanges. The example above results in:

      dateRanges => [{startDate => "7daysAgo", endDate => "1daysAgo"}]

    Note that endDate will default to "1daysAgo" if not present.

  • metrics

    metrics will be translated from a comma separated string, or passed on directly to Google Analytics if not. The example above results in this query:

      metrics => [{name => "ga:productListClicks"}, {name => "ga:productListViews"}]
  • order_by

    order_by can be used as a simpler version to orderBys. The example above results in:

      orderBys => [{fieldName => "ga:productListClicks", sortOrder => "DESCENDING'}]

    The sort order can be "asc" or "desc". Will result in "SORT_ORDER_UNSPECIFIED" unless present.

  • rows

    Alias for pageSize.

  • viewId

    viewId will be set from "view_id" if not present in the query.


  $promise = $selfg->get_report_p(\%query);

Same as "get_report", but returns a Mojo::Promise.


  $self = Mojo::GoogleAnalytics->new(%attrs);
  $self = Mojo::GoogleAnalytics->new(\%attrs);
  $self = Mojo::GoogleAnalytics->new("/path/to/credentials.json");

Used to construct a new Mojo::GoogleAnalytics object. Calling new() with a single argument will cause "from_file" to be called with that argument.


  $self = $self->mock;
  $self = $self->mock({batch_get_dir => "/path/to/some/dir"});
  $self = $self->mock({batch_get_uri => sub { my ($self, $c) = @_; }, token_uri => sub { my ($self, $c) = @_; }});

This method is useful when you want to test your application, but you don't want to ask Google for reports. mock() will be automatically called by "new" if the TEST_MOJO_GA_BATCH_GET_DIR environment variable i set. The arguments passed on to this method can be:

  • batch_get_dir

    Need to be an absolute path to a directory with the dummy response files for "batch_get".

    Defaults to TEST_MOJO_GA_BATCH_GET_DIR environment variable.

  • batch_get_uri

    A code ref that is used as an Mojolicious action. The default code ref provided by this module will look for a response file in batch_get_dir with the name $md5_sum.json, where the MD5 sum is calculated from the JSON request body. It will respond with an error message with the full path of the expected file, unless the file could be read.

  • token_uri

    A code ref that is used as an Mojolicious action. The default code ref will respond with a dummy bearer token and log you in.


Jan Henning Thorsen


This program is free software, you can redistribute it and/or modify it under the terms of the Artistic License version 2.0.