Notice: Over the next few months, we're reorganizing the App Engine documentation site to make it easier to find content and better align with the rest of Google Cloud products. The same content will be available, but the navigation will now match the rest of the Cloud products. If you have feedback or questions as you navigate the site, click Send Feedback.

Integrating with Google Analytics

Stay organized with collections Save and categorize content based on your preferences.

The Google Analytics Platform lets you measure user interactions with your business across various devices and environments. Google Analytics provides the resources to collect, store, process, and report on these user-interactions.

You can collect analytics on the client side and on the server side.

Client-side analytics collection

Use the Google Analytics APIs and SDKs to measure how users interact with your content and marketing initiatives. You can view user-interaction data in the Google Analytics user interface or use the Reporting APIs to fetch the data. For more details on client-side analytics collection, select the link below based on the type of your client:

  • Web Tracking (analytics.js) - Measure user interaction with websites or web applications.
  • Android - Measure user interaction with Android applications.
  • iOS - Measure user interaction with iOS applications.
  • Measurement Protocol - Measure user interaction in any environment with this low-level protocol.

Server-side analytics collection

Although App Engine provides a mechanism for logging events in your application, you can use Google Analytics to track specific server-side events in Google Analytics so that you can:

  • Analyze historical data - App Engine allows you to configure the maximum number of days, or size, of your log file. After that limit has been passed, you no longer have access to those log files. Tracking events in Google Analytics provides you a much longer lifespan into the visibility of past events.
  • Track key events - Log files can be verbose with various components of your application writing data to them. By using event tracking, you can pinpoint key events and track them, along with some metadata.
  • Work in the user interface - Take advantage of the rich user interface that Google Analytics provides to visualize, report, and export these server-side events.

To enable server-side analytics collection, you can use an HTTP client and make HTTP requests using the Google Analytics Measurement Protocol. For additional information, consult the Google Analytics developers guide for Event Tracking.

Sample Application

The sample application below shows how to track events in your App Engine application. The application makes an HTTP request and posts data about the event to Google Analytics.

Before you use the Google Analytics Measurement Protocol on App Engine, follow these steps:

  1. Create a Universal Analytics property and obtain the Tracking ID.

  2. Include the environment variables with your Tracking ID in the relevant configuration file for your runtime. For example, for the sample application shown below:

    Go

    The following is an example of the app.yaml file from a sample app:

    env_variables:
      GA_TRACKING_ID: UA-XXXXX-Y

    Java

    The following is an example of the app.yaml file from a sample app:

    env_variables:
      GA_TRACKING_ID: YOUR-GA-TRACKING-ID

    Node.js

    The following is an example of the app.flexible.yaml file from a sample app:

    env_variables:
      GA_TRACKING_ID: YOUR_TRACKING_ID

    PHP

    The following is an example of the app.yaml file from a sample app:

    env_variables:
      GA_TRACKING_ID: "YOUR-GA-TRACKING-ID"

    Python

    The following is an example of the app.yaml file from a sample app:

    env_variables:
        GA_TRACKING_ID: your-tracking-id

    Ruby

    The following is an example of the app.yaml file from a sample app:

    runtime: ruby
    env: flex
    entrypoint: bundle exec ruby app.rb
    
    env_variables:
      GA_TRACKING_ID: <your-tracking-id>

    .NET

    The following is an example of the appsettings.json file from a sample app:

    {
      "GaTrackingId": "your-google-analytics-tracking-id"
    }
    
    Replace `your-google-analytics-tracking-id` with the tracking ID you
    obtained from Google Analytics.
    

    Custom

    No additional information for this runtime.

  3. Before running the sample app locally, set the environment variables required by the app:

    Go

    export GA_TRACKING_ID=YOUR_TRACKING_ID
    

    Java

    export GA_TRACKING_ID=YOUR_TRACKING_ID
    

    Node.js

    export GA_TRACKING_ID=YOUR_TRACKING_ID
    npm install
    

    PHP

    export GA_TRACKING_ID=YOUR_TRACKING_ID
    composer install
    

    Python

    export GA_TRACKING_ID=YOUR_TRACKING_ID
    

    Ruby

    export GA_TRACKING_ID=YOUR_TRACKING_ID
    bundle install
    

    .NET

    Not applicable to this runtime.

    Custom

    No additional information for this runtime.

  4. Run the sample code locally using the command line. For example:

    Go

    go run analytics.go
    

    Java

    mvn clean appengine:run
    

    Node.js

    npm start
    

    PHP

    php -S localhost:8000
    

    Python

    python main.py
    

    Ruby

    bundle exec ruby app.rb
    

    .NET

    To run the sample app locally:

    Visual Studio

    1. Open dotnet-docs-samples\appengine\flexible\AppEngineFlex.sln with Visual Studio.

    2. Press F5.

    Command Line

    1. Run the following commands from the dotnet-docs-samples\appengine\flexible\Analytics directory:

      dotnet restore
      dotnet run
      
    2. In your web browser, enter the following address:

      http://localhost:5000/
      
    3. In your terminal window, press Ctrl+C to exit the web server.

    Custom

    No additional information for this runtime.

  5. Integrate the following code into your App Engine application to post event tracking data to Google Analytics:

    Go

    
    // Sample analytics demonstrates Google Analytics calls from App Engine flexible environment.
    package main
    
    import (
    	"errors"
    	"fmt"
    	"log"
    	"net"
    	"net/http"
    	"net/url"
    	"os"
    
    	uuid "github.com/gofrs/uuid"
    
    	"google.golang.org/appengine"
    )
    
    var gaPropertyID = mustGetenv("GA_TRACKING_ID")
    
    func mustGetenv(k string) string {
    	v := os.Getenv(k)
    	if v == "" {
    		log.Fatalf("%s environment variable not set.", k)
    	}
    	return v
    }
    
    func main() {
    	http.HandleFunc("/", handle)
    
    	appengine.Main()
    }
    
    func handle(w http.ResponseWriter, r *http.Request) {
    	if r.URL.Path != "/" {
    		http.NotFound(w, r)
    		return
    	}
    
    	if err := trackEvent(r, "Example", "Test action", "label", nil); err != nil {
    		fmt.Fprintf(w, "Event did not track: %v", err)
    		return
    	}
    	fmt.Fprint(w, "Event tracked.")
    }
    
    func trackEvent(r *http.Request, category, action, label string, value *uint) error {
    	if gaPropertyID == "" {
    		return errors.New("analytics: GA_TRACKING_ID environment variable is missing")
    	}
    	if category == "" || action == "" {
    		return errors.New("analytics: category and action are required")
    	}
    
    	v := url.Values{
    		"v":   {"1"},
    		"tid": {gaPropertyID},
    		// Anonymously identifies a particular user. See the parameter guide for
    		// details:
    		// https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#cid
    		//
    		// Depending on your application, this might want to be associated with the
    		// user in a cookie.
    		"cid": {uuid.Must(uuid.NewV4()).String()},
    		"t":   {"event"},
    		"ec":  {category},
    		"ea":  {action},
    		"ua":  {r.UserAgent()},
    	}
    
    	if label != "" {
    		v.Set("el", label)
    	}
    
    	if value != nil {
    		v.Set("ev", fmt.Sprintf("%d", *value))
    	}
    
    	if remoteIP, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
    		v.Set("uip", remoteIP)
    	}
    
    	// NOTE: Google Analytics returns a 200, even if the request is malformed.
    	_, err := http.PostForm("https://www.google-analytics.com/collect", v)
    	return err
    }
    

    Java

    @SuppressWarnings("serial")
    @WebServlet(name = "analytics", value = "")
    public class AnalyticsServlet extends HttpServlet {
    
      @Override
      public void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws IOException, ServletException {
        String trackingId = System.getenv("GA_TRACKING_ID");
        HttpClient client = HttpClientBuilder.create().build();
        URIBuilder builder = new URIBuilder();
        builder
            .setScheme("http")
            .setHost("www.google-analytics.com")
            .setPath("/collect")
            .addParameter("v", "1") // API Version.
            .addParameter("tid", trackingId) // Tracking ID / Property ID.
            // Anonymous Client Identifier. Ideally, this should be a UUID that
            // is associated with particular user, device, or browser instance.
            .addParameter("cid", "555")
            .addParameter("t", "event") // Event hit type.
            .addParameter("ec", "example") // Event category.
            .addParameter("ea", "test action"); // Event action.
        URI uri = null;
        try {
          uri = builder.build();
        } catch (URISyntaxException e) {
          throw new ServletException("Problem building URI", e);
        }
        HttpPost request = new HttpPost(uri);
        client.execute(request);
        resp.getWriter().println("Event tracked.");
      }
    }

    Node.js

    const express = require('express');
    const fetch = require('node-fetch');
    
    const app = express();
    app.enable('trust proxy');
    
    // The following environment variable is set by app.yaml when running on App
    // Engine, but will need to be set manually when running locally. See README.md.
    const {GA_TRACKING_ID} = process.env;
    
    const trackEvent = (category, action, label, value) => {
      const data = {
        // API Version.
        v: '1',
        // Tracking ID / Property ID.
        tid: GA_TRACKING_ID,
        // Anonymous Client Identifier. Ideally, this should be a UUID that
        // is associated with particular user, device, or browser instance.
        cid: '555',
        // Event hit type.
        t: 'event',
        // Event category.
        ec: category,
        // Event action.
        ea: action,
        // Event label.
        el: label,
        // Event value.
        ev: value,
      };
    
      return fetch('http://www.google-analytics.com/debug/collect', {
        params: data,
      });
    };
    
    app.get('/', async (req, res, next) => {
      // Event value must be numeric.
      try {
        await trackEvent(
          'Example category',
          'Example action',
          'Example label',
          '100'
        );
        res.status(200).send('Event tracked.').end();
      } catch (error) {
        // This sample treats an event tracking error as a fatal error. Depending
        // on your application's needs, failing to track an event may not be
        // considered an error.
        next(error);
      }
    });
    
    const PORT = parseInt(process.env.PORT) || 8080;
    app.listen(PORT, () => {
      console.log(`App listening on port ${PORT}`);
      console.log('Press Ctrl+C to quit.');
    });
    

    PHP

    $baseUri = 'http://www.google-analytics.com/';
    $client = new GuzzleHttp\Client(['base_uri' => $baseUri]);
    $formData = [
        'v' => '1',  # API Version.
        'tid' => $trackingId,  # Tracking ID / Property ID.
        # Anonymous Client Identifier. Ideally, this should be a UUID that
        # is associated with particular user, device, or browser instance.
        'cid' => '555',
        't' => 'event',  # Event hit type.
        'ec' => 'Poker',  # Event category.
        'ea' => 'Royal Flush',  # Event action.
        'el' => 'Hearts',  # Event label.
        'ev' => 0,  # Event value, must be an integer
    ];
    $gaResponse = $client->request('POST', 'collect', ['form_params' => $formData]);

    Python

    import logging
    import os
    
    from flask import Flask
    import requests
    
    
    app = Flask(__name__)
    
    
    # Environment variables are defined in app.yaml.
    GA_TRACKING_ID = os.environ['GA_TRACKING_ID']
    
    
    def track_event(category, action, label=None, value=0):
        data = {
            'v': '1',  # API Version.
            'tid': GA_TRACKING_ID,  # Tracking ID / Property ID.
            # Anonymous Client Identifier. Ideally, this should be a UUID that
            # is associated with particular user, device, or browser instance.
            'cid': '555',
            't': 'event',  # Event hit type.
            'ec': category,  # Event category.
            'ea': action,  # Event action.
            'el': label,  # Event label.
            'ev': value,  # Event value, must be an integer
            'ua': 'Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14'
        }
    
        response = requests.post(
            'https://www.google-analytics.com/collect', data=data)
    
        # If the request fails, this will raise a RequestException. Depending
        # on your application's needs, this may be a non-error and can be caught
        # by the caller.
        response.raise_for_status()
    
    
    @app.route('/')
    def track_example():
        track_event(
            category='Example',
            action='test action')
        return 'Event tracked.'
    
    
    @app.errorhandler(500)
    def server_error(e):
        logging.exception('An error occurred during a request.')
        return """
        An internal error occurred: <pre>{}</pre>
        See logs for full stacktrace.
        """.format(e), 500
    
    
    if __name__ == '__main__':
        # This is used when running locally. Gunicorn is used to run the
        # application on Google App Engine. See entrypoint in app.yaml.
        app.run(host='127.0.0.1', port=8080, debug=True)

    Ruby

    require "sinatra"
    require "net/http"
    
    # The following environment variable is set by app.yaml when running on GAE,
    # but will need to be manually set when running locally. See README.md.
    GA_TRACKING_ID = ENV["GA_TRACKING_ID"]
    
    def track_event category, action, label, value
      # Anonymous Client ID.
      # Ideally, this should be a UUID that is associated
      # with particular user, device, or browser instance.
      client_id = "555"
    
      Net::HTTP.post_form(
        URI("http://www.google-analytics.com/collect"),
        v:   "1",             # API Version
        tid: GA_TRACKING_ID,  # Tracking ID / Property ID
        cid: client_id,       # Client ID
        t:   "event",         # Event hit type
        ec:  category,        # Event category
        ea:  action,          # Event action
        el:  label,           # Event label
        ev:  value            # Event value
      )
    end
    
    get "/" do
      track_event "Example category", "Example action", "Example label", "123"
    
      "Event tracked."
    end

    .NET

    HttpClient http = new HttpClient()
    {
        BaseAddress = new Uri("http://www.google-analytics.com/")
    };
    var content = new FormUrlEncodedContent(
        new Dictionary<string, string>() {
            { "v" , "1" },  // API Version.
            { "tid" , Configuration["GaTrackingId"] },  // Tracking ID / Property ID.
            // Anonymous Client Identifier. Ideally, this should be a UUID that
            // is associated with particular user, device, or browser instance.
            { "cid" , "555" },
            { "t" , "event" },  // Event hit type.
            { "ec" , "Poker" },  // Event category.
            { "ea" , "Royal Flush" },  // Event action.
            { "el" , "Hearts" },  // Event label.
            { "ev" , "0" },  // Event value, must be an integer
        });
    var post = http.PostAsync("collect", content);
    

    Custom

    No additional information for this runtime.

If you have enabled the setting in your Google Analytics Admin console to exclude traffic from spiders and bots, or if you are using Google Analytics 4 (which filters this traffic automatically), you might not see Analytics results from App Engine clients. These scenarios filter out the default App Engine user agent. To see App Engine results, include the ua parameter in your tracking data and set it to a custom value.