Sending Data to Google Analytics

The last line of the JavaScript tracking snippet adds a send command to the ga() command queue to send a pageview to Google Analytics:

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');

The object that is doing the sending is the tracker that was scheduled for creation in the previous line of code, and the data that gets sent is the data stored on that tracker.

This guide describes the various ways to send data to Google Analytics and explains how to control what data gets sent.

Hits, hit types, and the Measurement Protocol

When a tracker sends data to Google Analytics it's called sending a hit, and every hit must have a hit type. The JavaScript tracking snippet sends a hit of type pageview; other hit types include screenview, event, transaction, item, social, exception, and timing. This guide outlines the concepts and methods common to all hit types. Individual guides for each hit type can be found under the section Tracking common user interactions in the left-side navigation.

The hit is an HTTP request, consisting of field and value pairs encoded as a query string, and sent to the Measurement Protocol.

If you have your browser's developers tools open when you load a page that uses analytics.js, you can see the hits being sent in the network tab. Look for requests sent to google-analytics.com/collect.

What data gets sent

When sending a hit to the Measurement Protocol, trackers send all of the fields that are currently stored and are valid Measurement Protocol parameters. For example, fields like title and location are sent but cookieDomain and hitCallback are not.

In some cases, you want to send fields to Google Analytics for the current hit but not for any subsequent hits. An example of this is an event hit where the eventAction and eventLabel fields are relevant to the current hit only.

To send fields with the current hit only, you can pass them as arguments to the send method. To have field data sent with all subsequent hits, you should update the tracker using the set method.

The send method

A tracker's send method can be called directly on the tracker object itself or by adding a send command to the ga() command queue. Since most of the time you don't have a reference to the tracker object, using the ga() command queue is the recommended way to send tracker data to Google Analytics.

Using the ga() command queue

The signature for adding a send command to the ga() command queue is as follows:

ga('[trackerName.]send', [hitType], [...fields], [fieldsObject]);

As mentioned above, the values specified via in the hitType, ...fields, and fieldsObject parameters get sent for the current hit only. They do not get stored on the tracker object, nor are they sent with subsequent hits.

If any of the fields passed with the send command are already set on the tracker object, the values passed in the command will be used rather than the values stored on the tracker.

Calls to the send command must specify a hitType and, depending on the type specified, other parameters may be required as well. See the individual guides for tracking common user interactions in the left-side navigation for more details.

The simplest way to use the send command, that works for all hit types, is to pass all fields using the fieldsObject parameter. For example:

ga('send', {
  hitType: 'event',
  eventCategory: 'Video',
  eventAction: 'play',
  eventLabel: 'cats.mp4'
});

For convenience, certain hit types allow commonly used fields to be passed directly as arguments to the send command. For example, the above send command for the "event" hit type could be rewritten as:

ga('send', 'event', 'Video', 'play', 'cats.mp4');

For a complete list of what fields can be passed as arguments for the various hit types, see the "parameters" section of the send method reference.

Using a named tracker

If you're using a named tracker instead of the default tracker, you can pass its name in the command string.

The following send command will be called on the tracker named "myTracker":

ga('myTracker.send', 'event', 'Video', 'play', 'cats.mp4');

On the tracker object itself

If you have a reference to the tracker object, you can call that tracker's send method directly:

ga(function(tracker) {
  tracker.send('event', 'Video', 'play', 'cats.mp4');
});

Knowing when the hit has been sent

In some cases you need to know when a hit is done being sent to Google Analytics, so you can take action immediately afterward. This is common when you need to record a particular interaction that would take a user away from the current page. Many browsers stop executing JavaScript as soon as the page starts unloading, which means your analytics.js commands to send hits may never run.

An example of this is when you want to send an event to Google Analytics to record that a user clicked on a form's submit button. In most cases, clicking the submit button will immediately start loading the next page, and any ga('send', ...) commands will not run.

The solution to this is to intercept the event to stop the page from unloading. You can then send your hit to Google Analytics as usual, and once the hit is done being sent, you can resubmit the form programmatically.

hitCallback

To be notified when a hit is done sending, you set the hitCallback field. hitCallback is a function that gets called as soon as the hit has been successfully sent.

The following example shows how to cancel a form's default submit action, send a hit to Google Analytics, and then resubmit the form using the hitCallback function:

// Gets a reference to the form element, assuming
// it contains the id attribute "signup-form".
var form = document.getElementById('signup-form');

// Adds a listener for the "submit" event.
form.addEventListener('submit', function(event) {

  // Prevents the browser from submitting the form
  // and thus unloading the current page.
  event.preventDefault();

  // Sends the event to Google Analytics and
  // resubmits the form once the hit is done.
  ga('send', 'event', 'Signup Form', 'submit', {
    hitCallback: function() {
      form.submit();
    }
  });
});

Handling timeouts

The above example works nicely, but it has one serious problem. If (for whatever reason) the analytics.js library fails to load, the hitCallback function will never run. And if the hitCallback function never runs, users will never be able to submit the form.

Whenever you put critical site functionality inside the hitCallback function, you should always use a timeout function to handle cases where the analytics.js library fails to load.

The next example updates the above code to use a timeout. If one second passes after the user clicks the submit button and the hitCallback has not run, the form is resubmitted anyway.

// Gets a reference to the form element, assuming
// it contains the id attribute "signup-form".
var form = document.getElementById('signup-form');

// Adds a listener for the "submit" event.
form.addEventListener('submit', function(event) {

  // Prevents the browser from submitting the form
  // and thus unloading the current page.
  event.preventDefault();

  // Creates a timeout to call `submitForm` after one second.
  setTimeout(submitForm, 1000);

  // Keeps track of whether or not the form has been submitted.
  // This prevents the form from being submitted twice in cases
  // where `hitCallback` fires normally.
  var formSubmitted = false;

  function submitForm() {
    if (!formSubmitted) {
      formSubmitted = true;
      form.submit();
    }
  }

  // Sends the event to Google Analytics and
  // resubmits the form once the hit is done.
  ga('send', 'event', 'Signup Form', 'submit', {
    hitCallback: submitForm
  });
});

If you're using the above pattern in many places throughout your site, it's probably easier to create a utility function to handle timeouts.

The following utility function accepts a function as input and returns a new function. If the returned function is called before the timeout period (the default timeout is one second), it clears the timeout and invokes the input function. If the returned function isn't called before the timeout period, the input function is called regardless.

function createFunctionWithTimeout(callback, opt_timeout) {
  var called = false;
  function fn() {
    if (!called) {
      called = true;
      callback();
    }
  }
  setTimeout(fn, opt_timeout || 1000);
  return fn;
}

Now you can easily wrap all hitCallback functions with a timeout to ensure your site works as expected even in cases where your hits fail to send or the analytics.js library never loads.

// Gets a reference to the form element, assuming
// it contains the id attribute "signup-form".
var form = document.getElementById('signup-form');

// Adds a listener for the "submit" event.
form.addEventListener('submit', function(event) {

  // Prevents the browser from submitting the form
  // and thus unloading the current page.
  event.preventDefault();

  // Sends the event to Google Analytics and
  // resubmits the form once the hit is done.
  ga('send', 'event', 'Signup Form', 'submit', {
    hitCallback: createFunctionWithTimeout(function() {
      form.submit();
    })
  });
});

Specifying different transport mechanisms

By default, analytics.js picks the HTTP method and transport mechanism with which to optimally send hits. The three options are 'image' (using an Image object), 'xhr' (using an XMLHttpRequest object), or 'beacon' using the new navigator.sendBeacon method.

The former two methods share the problem described in the previous section (where hits are often not sent if the page is being unloaded). The navigator.sendBeacon method, by contrast, is a new HTML feature created to solve this problem.

If your user's browser supports the navigator.sendBeacon, you can specify 'beacon' as the transport mechanism and not have to worry about setting a hit callback.

The following code sets the transport mechanism to 'beacon' in browsers that support it.

ga('create', 'UA-XXXXX-Y', 'auto');

// Updates the tracker to use `navigator.sendBeacon` if available.
ga('set', 'transport', 'beacon');

Next steps

Measuring certain types of user interactions can sometimes require complex implementations. However, in many cases these implementations have already been developed and made available as analytics.js plugins. The next guide explains how to use analytics.js plugins with the ga() command queue.