How to Use the Google Analytics 4 Measurement Protocol – Python Client

May 6, 2021

What Is the GA4 Measurement Protocol?

The GA4 Measurement Protocol (GA4MP) is essentially an API that allows developers to make POST HTTP requests to send Google Analytics (GA) events directly to the GA server. This allows any device that can make HTTP calls to interact with GA, making the possibilities virtually endless. Primarily, though, this also empowers the sending of data collected offline to GA that can be post-dated up to 48 hours to align with online events. 

Today, we’ll focus on Adswerve’s Python client for the GA4MP but because the protocol is simply an HTTP request, the protocol can be called through any language that is able to interact with an API. As an example, take a look at the Adswerve Typescript implementation.

Please note that at the time of writing the GA4MP is in alpha, therefore, so is the GA4MP Python implementation. You can follow the status of the API here.

Let’s get started!


The GA4MP Python library is hosted on PyPi and therefore installing the client is as simple as using pip in your favourite virtual environment:

pip install ga4mp


In order to use the GA4MP, a user would need to acquire credentials to be validated by GA. The required credentials are:

1. measurement_id: The identifier for a Data Stream. Found in the Google Analytics UI under: Admin > Data Streams > choose your stream > Measurement ID.

2. api_secret: Generated through the Google Analytics UI. To create a new secret, navigate in the Google Analytics UI to: Admin > Data Streams > Choose Your Stream > Measurement Protocol API secrets > Create.

3. client_id: Instruction can be found at Get your Google API client ID.

Once you have the required credentials, they are simply strings that can either be stored in a json file or passed directly to the Python client to follow.

Basic Usage

The purpose of the GA4MP is to get events that occur outside of GA into GA, however this can take a few different forms:

1. When events occur, we want them sent to GA in real time.

2. We may be currently collecting events but are either not able to send them immediately (e.g. we are offline) or for some reason do not wish to.

3. We have collected events that we want to appear as hits that occured prior to our collecting them.

We show how to perform each of the above in the following sections:

1. Sending Real-Time Events

To send events in general, but specifically events in real time, we start by importing the `Ga4mp` class and instantiating the class with the credentials that we collected above. We read our credentials from a deserialized json dictionary but you can choose however you wish:

from ga4mp import Ga4mp

API_SECRET = credentials['API_SECRET']
CLIENT_ID = credentials['CLIENT_ID']

ga = Ga4mp(measurement_id = "MEASUREMENT_ID", api_secret = "API_SECRET", client_id="CLIENT_ID")

To send an event to GA, the client expects a list of events where each event is a Python dictionary. Each event dictionary should at minimum contain a `name` key and a `params` dictionary. The following shows an example of constructing a single event:

# Event parameters are a dictionary
event_parameters = {'paramater_key_1': 'parameter_1', 'paramater_key_2': 'parameter_2'}
# An event should be a dictionary
event = {'name': 'my_custom_event', 'params': event_parameters }
# Can send a list of multiple events
events = [event]

After collecting our events into a list we can send the event using the `send` method:


>>> INFO:ga4mp.ga4mp:Sending POST to:
>>>INFO:ga4mp.ga4mp:Batch Number: 1
>>>INFO:ga4mp.ga4mp:Status code: 204

As you can see in the output, the client sends a POST request to the GA server, and sends the data in batches. There is a limit of 25 events per request, but the client collects any number of events and sends them sequentially in batches of 25. You can learn about further limitations here.

Lastly, as status code is printed out to indicate if the request was successful or not. One of the following codes is deemed as acceptable: 200, 201, 204.

After sending your event, you can go to the Real Time overview in GA and see the hit!

Validating Events

To ensure that your events are sent successfully, the Python client checks the event names against any reserved event names, however, the GA4MP also has the functionality to validate whether the event list is adequately structured by sending an HTTP request to a validation server. To send a validation hit to the validation server, simply set the `validation_hit` argument to `True` to the `send` method as follows:


>>>INFO:ga4mp.ga4mp:Sending POST to:
>>>INFO:ga4mp.ga4mp:Batch Number: 1
>>>INFO:ga4mp.ga4mp:Status code: 200

Where you will see that the POST target has changed to the validation server.

2. Sending Postponed Events

Addressing our second scenario of sending events at a time after they were collected, we can send events using the `postpone` argument which simply stores the events in a list, and that list can be sent at an appropriate time:


This is useful as it is possible that we may be collecting event hits in real time and do not want to write code to manage the collection of the events along with their timestamp to be implemented later. After adding the events using the above method, the stored list can be sent as follows:


>>>INFO:ga4mp.ga4mp:Sending POST to:
>>>INFO:ga4mp.ga4mp:Batch Number: 1
>>>INFO:ga4mp.ga4mp:Status code: 204

3. Sending Historical Events

Lastly, we may want to back-date events that have just been collected but are relevant in the past. The Python client supports backdating events up to 48 hours by providing a Python `datetime` object to the `date` parameter of the `send` method:

import datetime
dt = - datetime.timedelta(hours=48)
ga.send(events, date=dt)

>>>INFO:ga4mp.ga4mp:Sending POST to:
>>>INFO:ga4mp.ga4mp:Setting event timestamp to: 2021-03-10 16:20:41.722364
>>>INFO:ga4mp.ga4mp:Timestamp of request is: 1615386041000000
>>>INFO:ga4mp.ga4mp:Batch Number: 1
>>>INFO:ga4mp.ga4mp:Status code: 204

Where it can be seen that the timestamp gets set as a unix timestamp in microseconds. 

What’s Next?

We can now send our custom events to GA! If you want to take the GA4MP Python client a little further, try out one of the following:

  • Star the repo on Github to be notified when features are added.
  • Contribute! The GA4MP is open source under a BSD-3 License and is open to Issues and Pull Requests.
  • Check out the API documentation here for further usage