Google Analytics

Management API - Using Java

This document explains how to access the Management API using the Java programming language and walks through a simple example. For an introduction to purpose of the the Management API and the data it provides, see Getting Started.

  1. Introduction
  2. Before You Begin
  3. Authorization
  4. Instantiating a Service Object
  1. Making API Requests & Handling Errors
    1. Accounts
    2. Web Properties
    3. Views (Profiles)
    4. Goals
    5. Advanced Segments
 

Introduction

The Google APIs Client Library for Java simplifies working with the Google Analytics Management API. It provides wrappers for retrieving authorization tokens, a simple interface for issuing API requests, and helpful libraries to parse the API responses into Java objects.

This guide describes a basic Java client application that exercises all the key steps needed to use the Management API:

  1. Retrieving a new OAuth 2.0 authorization token
  2. Instantiating a new authorized service object
  3. Executing API requests to retrieve configuration data
  4. Working with the responses
  5. Handling errors

You can download the full sample source code from Google APIs Client Library for Java.

Before You Begin

Before working with the sample code in this guide, you must do the following:

Get the library – Install Google APIs Client Library for Java, which provides all the classes to work with the Management API.

Register your application – Every request your application sends to the Management API must be authorized by an authenticated user. To authenticate users in the sample code, you must register your application to use an OAuth 2.0 token for an installed application in the Google Developers Console, as described in Authorization.

Set up your environment – Running the sample code in this guide requires that your build path contain the following:

  • google-api-client-1.5.0-beta.jar
  • google-oauth-client-1.5.0-beta.jar
  • dependencies/gson-1.6.jar
  • dependencies/guava-r09.jar
  • dependencies/jackson-core-asl-1.6.7.jar

All of these files can be downloaded from client library or from their respective projects.

Note: The sample code in this guide uses version 1.5.0-beta of the client library. As this library is in development, you might need to get slightly different versions of the library or dependencies. Be sure to check the Dependencies section of the client library setup guide.

After configuring these dependencies, you can run an application that uses the Java client library, such as the sample application in this guide.

Back to Top

Authorizing Requests

Just as you must log in to the Google Analytics interface in order to view your data, your application must also obtain authorization in order to access a user's Analytics data. Version 3.0 of the API supports authorization using OAuth 2.0 tokens.

To set up authorization, you need to register a new project in the Google Developers Console and configure it to use OAuth 2.0 for an installed application. Registration gives you the two things that you need in order to work with the API:

  • a unique clientId
  • a clientSecret

Note: For details about how to authorize OAuth 2.0 requests in other environments, such as server or client side web applications, see Authorizing requests.

When the sample application runs for the first time, it prompts the user to authorize access to their data by navigating to a URL and approving access. Once the approval is granted, they are given an authorization code. The user must supply this authorization code back to the application, at which time the application uses the code to get an OAuth 2.0 access token and a refresh token.

The application uses the access token to access a user's data from the API. The token is valid for an unspecified period of time. For efficiency, an application should reuse a token as long as possible. When a token becomes invalid, the API returns a 401 status code. The application can then use the refresh token to retrieve a new access token, as the following sample code does.

The Java client library provides two classes to implement this flow of authorization and refresh: NetHttpTransport and JacksonFactory.

NetHttpTransport netHttpTransport = new NetHttpTransport();
JacksonFactory jacksonFactory = new JacksonFactory();

private static final String CLIENT_ID = "OBTAIN_FROM_CLOUD_CONSOLE";
private static final String CLIENT_SECRET = "OBTAIN_FROM_CLOUD_CONSOLE";

// Redirect URL for client side installed apps.
private static final String REDIRECT_URL = "urn:ietf:wg:oauth:2.0:oob";

// Generate the URL to send the user to grant access.
String authorizationUrl = new GoogleAuthorizationRequestUrl(clientId, redirectUrl, scope).build();

// Direct user to the authorization URI.
System.out.println("Go to the following link in your browser:");
System.out.println(authorizationUrl);

// Get authorization code from user.
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.println("What is the authorization code?");
String authorizationCode = null;
try {
  authorizationCode = in.readLine();
} catch (IOException ioe) {
  ioe.printStackTrace();
}

// Use the authorization code to get an access token and a refresh token.
AccessTokenResponse response = null;
try {
  response = new GoogleAccessTokenRequest.GoogleAuthorizationCodeGrant(
      httpTransport, jsonFactory, CLIENT_ID, CLIENT_SECRET, authorizationCode,
          REDIRECT_URL).execute();
} catch (IOException ioe) {
  ioe.printStackTrace();
}

// Use the access and refresh tokens to get a new GoogleAccessProtectedResource.
GoogleAccessProtectedResource googleAccessProtectedResource =
    new GoogleAccessProtectedResource(response.accessToken, httpTransport, jsonFactory,
        clientId, clientSecret, response.refreshToken);

After the authentication code executes, the application has a GoogleAccessProtectedResource object it can use to instantiate a service object to work with the API.

Back to Top

Instantiating a Service Object

The Java client library provides a single class Analytics to access all the data through the Management API. The application uses its googleAccessProtectedResource object to instantiate an Analytics service object.

Analytics analytics = new Analytics(netHttpTransport, googleAccessProtectedResource, jacksonFactory);
analytics.setApplicationName("My Management Demo");

The parameters to the Analytics constructor are the three objects created in the Authorization flow above.

After the application instantiates the Analytics service object, it can start making authorized requests to the Management API.

Back to Top

Making API Requests & Handling Errors

Making requests

An application uses the Analytics service object to make all requests to the Management API. The five kinds of request to the API are all pretty similar: for a given authenticated user, each request returns a list of one kind of entity. The list is called a collection and the entity is called a resource.

As explained in the Management API Overview, the types of entities are organized in a hierarchy: An Account is a top-level entity, each Account can have a collection of Web Properties as children, and so on. To find the particular resource or resources you are seeking, you:

  • Request a collection of a user's top-level resources (Account or Segment).
  • Use the childLink property of a resource to get a URI for the collection of its child resources.
  • Iterate through the child resources in the collection and examine their fields, including their Entity IDs.
  • Traverse the hierarchy by making further requests on the Entity IDs of a child resource to retrieve the collection of its own children.

For example, an Account is a top-level resource. The following code uses the service object instantiated earlier to call the API to get a list of the user's accounts.

try {
  // Get a list of Google Analytics accounts the user has access to.
  Accounts accounts = analytics.management.accounts.list().execute();

} catch(HttpResponseException e) {
  // Handle API specific errors.
  handleApiError(e);

} catch (IOException ioe) {
  // Handle errors that occur while parsing the response.
  ioe.printStackTrace();
}

The code above calls execute to retrieve parsed data in the Accounts class. If you prefer to access the raw API response instead, use the executeUnparsed() method:

  HttpResponse response = analytics.management.accounts.list().executeUnparsed();

If the call succeeds, an object containing a list of all the user's accounts is stored in the accounts object. The sample program then makes subsequent calls on the accounts object to access its children and descend the hierarchy.

If the call fails, then an error occurred that an application needs to handle, as shown below.

Handling errors

The Analytics service object can throw two kinds of exception:

  • HttpResponseException exceptions result from API errors. Each kind of API error returns a particular HTTP status code and a textual description of the problem.
  • IOException exceptions generally result from library errors when parsing the API response into Java objects.

The following code parses the HTTP response found in the HttpResponseException to get both the status code and description.

private void handleApiError(HttpResponseException e) {
  GoogleJsonError errorResponse = null;

  // Try to parse the error response.
  try {
    errorResponse = GoogleJsonError.parse(jsonParser, e.getResponse());
  } catch (IOException ioe) {
    // An error occurred parsing the error response.
    ioe.printStackTrace();
    return;
  }

  if (errorResponse.code == 401) {
    // Code 401 means the user authorization token is invalid.
    // The application can address this error by enabling the user to get a new token.
    System.err.println("Invalid authorization token, please get a new one.");
  } else {
    // All other status codes indicate an API or service issue.
    // See the error message for details.
    System.err.println(errorResponse.code + " Error: " + errorResponse.message);
    for (ErrorInfo error : errorResponse.errors) {
      System.err.println(jsonParser.toString(error));
    }
  }
}

The sample code above handles two kinds of exception:

  • Authorization error. The API returns a 401 HTTP status code because the OAuth 2.0 token is invalid. The application needs to either use the refresh token or get a new access token.
  • Management API error. The API returns different status codes, each with a descriptive message stating what caused the error. The sample application prints them to inform the developer how to adjust the query.

    The full list of error codes and their messages is in Error Codes.

Every request an application makes to the Management API should include error handling. But to avoid cluttering the examples with error-handling code, the rest of this guide shows only the code for API requests and responses.

Back to Top

Working with Accounts

A Google Analytics Account is a top level entity in the Management API. It has no parent, and it has a collection of Webproperty resources as children. To request a list of Analytics accounts to which the user has access, use the Analytics service object instantiated in the example above.

Accounts accounts = analytics.management.accounts.list().execute();

The results of the list method are in the accounts object. The following code shows how to iterate through the results. For an explanation of all the properties of an Account resource, see Accounts Collection.

for (Account account : accounts.getItems()) {
  System.out.println("Account ID: " + account.getId());
  System.out.println("Account Name: " + account.getName());
  System.out.println("Account Created: " + account.getCreated());
  System.out.println("Account Updated: " + account.getUpdated());
}

The sample application uses the Account ID returned by getId as a parameter to subsequent queries shown in upcoming sections.

Back to Top

Working with Web Properties

A Google Analytics web property is at the second level in the account hierarchy; each Webproperty has a single account resource as its parent and can have a child that is a collection of one or more view (profile) resources.

An application can request a list of the web properties for one of a user's accounts by using the Analytics service object and passing the Account ID to the list method. For example, the following code requests a list of all web properties for the account with ID 12345.

Webproperties webproperties = analytics.management.webproperties.list("12345").execute();

The list method for web properties requires an accountId parameter that specifies which account to use when retrieving the list of web properties. To retrieve the web properties for all of the user's accounts, you can use the wildcard ~all as the accountId, as shown in the following code.

Webproperties webproperties = analytics.management.webproperties.list("~all").execute();

The results of the list method are stored in the webproperties object. The following code shows how to iterate through them. For an explanation of all the properties of a Webproperty resource, see Webproperties Collection.

for (Webproperty webproperty : webproperties.getItems()) {
  System.out.println("Account ID: " + webproperty.getAccountId());
  System.out.println("Web Property ID: " + webproperty.getId());
  System.out.println("Web Property Name: " + webproperty.getName());
  System.out.println("Web Property Internal Id: " + webproperty.getInternalWebPropertyId());
  System.out.println("Web Property Website URL: " + webproperty.getWebsiteUrl());
  System.out.println("Web Property Created: " + webproperty.getCreated());
  System.out.println("Web Property Updated: " + webproperty.getUpdated());
}

The sample application uses the Web Property ID returned by getId as a parameter to subsequent queries in upcoming sections of this guide.

Back to Top

Working with Views (Profiles)

A Google Analytics View (Profile) resource is at the third level in the Account hierarchy. Each View (Profile) has a single Webproperty resource as its parent in the hierarchy and can have a collection of zero or more Goal resources as children.

The View (Profile) resource plays an important role in retrieving report data through the Core Reporting API, because accessing the Data Feed requires a View (Profile) ID as a tableId parameter.

You can request a list of views (profiles) available to the user by calling the list method for Views (Profiles). This method requires both an accountId and a webPropertyId parameter.

To request view (profiles) for a particular account and web property, you specify each ID, as shown in the following example code.

Profiles profiles = analytics.management.profiles.list("12345", "UA-12345-1").execute();

To request the views (profiles) for all the web properties of a particular account, you can use the ~all wildcard in place of the webPropertyId. The result of the following code is a list of Views (Profiles) for all the web properties of the account with ID 12345.

Profiles profiles = analytics.management.profiles.list("12345", "~all").execute();

To request all views (profiles) available to the user, you use the ~all wildcard for both ID parameters. The result of the following code is a list of views (profiles) for all the web properties of all the user's accounts.

Profiles profiles = analytics.management.profiles.list("~all", "~all").execute();

Note: In all Management API requests, you cannot specify a particular child ID as a parameter if you used ~all for its parent. For example, the following request is invalid because it passes accountId as the parent of the web property UA-123-1 rather than a specific accountId.

analytics.management.profiles.list("~all", "UA-123-1")

The results from the list method are stored in the profiles object. The following code shows how to iterate through them. For an explanation of all the properties of a View (Profile) resource, see Views (Profiles) Collection.

for (Profile profile : profiles.getItems()) {
  System.out.println("Account ID: " + profile.getAccountId());
  System.out.println("Web Property ID: " + profile.getWebPropertyId());
  System.out.println("Web Property Internal ID: " + profile.getInternalWebPropertyId());
  System.out.println("View (Profile) ID: " + profile.getId());
  System.out.println("View (Profile) Name: " + profile.getName());

  System.out.println("View (Profile) defaultPage: " + profile.getDefaultPage());
  System.out.println("View (Profile) Exclude Query Parameters: "
      + profile.getExcludeQueryParameters());
  System.out.println("View (Profile) Site Search Query Parameters: "
      + profile.getSiteSearchQueryParameters());
  System.out.println("View (Profile) Site Search Category Parameters: "
      + profile.getSiteSearchCategoryParameters());

  System.out.println("View (Profile) Currency: " + profile.getCurrency());
  System.out.println("View (Profile) Timezone: " + profile.getTimezone());
  System.out.println("View (Profile) Updated: " + profile.getUpdated());
  System.out.println("View (Profile) Created: " + profile.getCreated());
}

In the next section, the sample application uses the View (Profile) ID returned by getId as a parameter for requesting a list of Goal resources in the next section. The important use of this ID in a real application is to pass it as the ids parameter to a Data Feed request in the Core Reporting API.

Back to Top

Working with Goals

A Google Analytics Goal is at the fourth and lowest level in the account hierarchy; goals have no child entities. Each Goal resource has a single View (Profile) resource as its parent in the hierarchy. The Goal data provided by the Management API describes how a goal is configured: its name, value, type, and whether or not it is active.

The sample application requests a list of a user's goals by calling the list method for Goals on the Analytics service object. The method requires an accountId, a webPropertyId, and a profileId as parameters.

To request goals for a single view (profile), you specify the ID of an account, web property, and view (profile), as in the following code.

Goals goals = analytics.management.goals.list("12345", "UA-12345-1", "420").execute();

To request all goals for all views (profiles) for the user, you can use the ~all wildcard, as in the following code.

Goals goals = analytics.management.goals.list("~all", "~all", "~all").execute();

Note: In all Management API requests, you cannot specify a particular child ID as a parameter if you used ~all for its parent.

For example, the following list request is invalid because it passes the specific profileID 420 but uses the wildcard ~all as the webPropertyId.

Goals goals = analytics.management.goals.list("~all", "~all", "420").execute();

The results of the list method for goals are stored in the goals object. The following code shows how to iterate through them. For an explanation of all the properties of a Goal resource, see Goals Collection.

for (Goal goal : goals.getItems()) {
  System.out.println("Account ID: " + goal.getAccountId());
  System.out.println("Web Property ID: " + goal.getWebPropertyId());
  System.out.println("Web Property Internal Id: " + goal.getInternalWebPropertyId());
  System.out.println("View (Profile) ID: " + goal.getId());

  System.out.println("Goal Number: " + goal.getId());
  System.out.println("Goal Name: " + goal.getName());
  System.out.println("Is Goal Active: " + goal.getActive());
  System.out.println("Goal Value: " + goal.getValue());
  System.out.println("Goal Type: " + goal.getType());
  System.out.println("Goal Created: " + goal.getCreated());
  System.out.println("Goal Updated: " + goal.getUpdated());

  if (goal.getUrlDestinationDetails() != null) {
    printGoalUrlDestinationDetails(goal.getUrlDestinationDetails());

  } else if (goal.getSessionTimeOnSiteDetails() != null) {
    printGoalSessionTimeOnSiteDetails(goal.getSessionTimeOnSiteDetails());

  } else if (goal.getSessionNumPagesDetails() != null) {
    printGoalSessionNumPagesDetails(goal.getSessionNumPagesDetails());

  } else if (goal.getEventDetails() != null) {
    printGoalEventDetails(goal.getEventDetails());
  }
}

Back to Top

Goal properties

When a user creates a goal in Analytics, they choose one of four different types, as explained in Setting Up Goals. They are:

  • URL_DESTINATION
  • VISIT_TIME_ON_SITE
  • VISIT_NUM_PAGES
  • EVENT

The different types of goal have different corresponding data. The following sections show code for printing each of the four kinds of goal.

URL_DESTINATION Goal

A URL destination goal is met when a user reaches a single page or group of pages specified in the goal definition. Each URL Destination goal can be configured with a number of steps that lead up to the goal. The Management API returns all configured steps. The following sample code shows how to iterate through them.

public void printGoalUrlDestinationDetails(GoalUrlDestinationDetails destination) {
  System.out.println("Goal Url: " + destination.getUrl());
  System.out.println("Case Sensitive: " +  destination.getCaseSensitive());
  System.out.println("Match Type: " +  destination.getMatchType());
  System.out.println("First step Required: " +  destination.getFirstStepRequired());

  if (destination.getSteps() != null) {
    System.out.println("Goal Steps: ");
    for (GoalUrlDestinationDetailsSteps step : destination.getSteps()) {
      System.out.println("Step Number: " + step.getNumber());
      System.out.println("Name: " + step.getName());
      System.out.println("URL: " + step.getUrl());
    }
  } else {
    System.out.println("No Steps Configured");
  }
}

VISIT_TIME_ON_SITE Goal

A Time on Site goal specifies the amount of time a user spends on the user's site; it is met when a user spends that total amount of time on the site during their session.

public void printGoalSessionTimeOnSiteDetails(
    GoalSessionTimeOnSiteDetails sessionTimeOnSiteDetails) {

  System.out.println("Goal Type:  VISIT_TIME_ON_SITE");
  System.out.println("VISIT_TIME_ON_SITE - Comparison Type: "
      + sessionTimeOnSiteDetails.getComparisonType());
  System.out.println("VISIT_TIME_ON_SITE - Comparison Value: "
      + sessionTimeOnSiteDetails.getComparisonValue());
}

VISIT_NUM_PAGES Goal

A Pages/Session goal specifies a page-session threshold. It is met when the number of pages a user visits during a session reaches the threshold.

public void printGoalSessionNumPagesDetails(GoalSessionNumPagesDetails numPagesDetails) {
  System.out.println("Goal Type:  VISIT_NUM_PAGES");
  System.out.println("VISIT_NUM_PAGES - Comparison Type: "
      +  numPagesDetails.getComparisonType());
  System.out.println("VISIT_NUM_PAGES - Comparison Value: "
      +  numPagesDetails.getComparisonValue());
}

EVENT Goal

Event goals can be configured to match multiple conditions, as explained in Setting Up Goals. The Management API returns all configurations as a list of conditions.

The values in a condition depend on the Goal type property. VALUE conditions use the comparisonType and comparisonValue properties, while CATEGORY, ACTION, and LABEL conditions use the matchType and expression properties.

The following sample code iterates through a list of conditions of an Event goal and prints each according to its type.

public void printGoalEventDetails(GoalEventDetails eventDetails) {
  System.out.println("Goal Type:  EVENT");
  System.out.println("EVENT - Use Event Value: " +  eventDetails.getUseEventValue());

  if (eventDetails.getEventConditions() != null) {
    System.out.println("Goal Conditions: ");
    for (GoalEventDetailsEventConditions conditions : eventDetails.getEventConditions()) {
      System.out.println("Type: " + conditions.getType());

      if (conditions.getType().equals("VALUE")) {
        System.out.println("Comparison Type: " + conditions.getComparisonType());
        System.out.println("Comparison Value: " + conditions.getComparisonValue());
      } else {
        System.out.println("matchType: " + conditions.getMatchType());
        System.out.println("expression: " + conditions.getExpression());
      }
    }
  }
}

The formats and meanings of all the properties of the four kinds of Goal resource are explained in Goals Collection.

Back to Top

Working with Advanced Segments

An advanced segment is a top level entity in the Management API. It has no parent and no children. Google Analytics provides a default set of advanced segments, but users can also create and save their own custom segments through the Analytics web interface. An important use of advanced segments is to separate out a subset of sessions when retrieving data from the Core Reporting API.

The list method on Segments provides access to both the default and custom segments available to the authenticated user. The sample application requests a list of a user's default and custom segments by calling the Segments list method on the Analytics service object by using the following code.

Segments segments = analytics.management.segments.list().execute();

The results of the list method are in the segments object. The following code shows how to iterate through the results. For a list of all the properties of a Segment resource, see Segments Collection.

public void printSegments(Segments segments) {
  for (Advancedsegment segment : segments.getItems()) {
    System.out.println("Advanced Segment ID: " + segment.getId());
    System.out.println("Advanced Segment Name: " + segment.getName());
    System.out.println("Advanced Segment Definition: " + segment.getDefinition());
  }

  // These fields are only set for custom segments and not default segments.
  if (segment.getCreated() != null) {
    System.out.println("Advanced Segment Created: " + segment.getCreated());
    System.out.println("Advanced Segment Updated: " + segment.getUpdated());
  }
}

Advanced segments are explained in Advanced Segmentation. In a real application, you can use the value returned in the id property as the segment parameter to the Core Reporting API Data Feed. All negative ID values are default segments while all positive values are custom segments defined for the authenticated user.

Back to Top




Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.