Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
This library provides an interface for sending data to Google Analytics, supporting the GA4 Measurement Protocol.
NOTE: This project is in beta and will be continually updated to cover relevant features of the GA4 Measurement Protocol. Please feel free to file issues for feature requests.
Email: analytics-help@adswerve.com
The easiest way to install GA4 Measurement Protocol Support for Python is directly from PyPi using pip
by running the following command:
pip install ga4mp
NOTE: Recent changes have added new platform specific subclasses. In order to take advantage of new functionality, you will need to update the class name of the GA4 object(s) being created in your code.
This library supports both gtag and Firebase data collection models. When creating your tracking object, use either GtagMP
or FirebaseMP
, depending on your needs.
The required credentials for sending events to GA4 using gtag comprise the following:
Credential | Description |
---|---|
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 |
measurement_id | The identifier for a Data Stream. Found in the Google Analytics UI under: Admin > Data Streams > choose your stream > Measurement ID |
client_id | A unique identifier for a client, representing a specific browser/device. |
The required credentials for sending events to Firebase comprise the following:
Credential | Description |
---|---|
api_secret | Generated throught 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 |
firebase_app_id | The identifier for a Firebase app. Found in the Firebase console under: Project Settings > General > Your Apps > App ID. |
app_instance_id | A unique identifier for a Firebase app instance. See Required parameters > 2. JSON body for details. |
Create your credentials.json file and put in your "./credentials" subdirectory.
{"API_SECRET": "<YOUR_API_SECRET>",
"MEASUREMENT_ID": "<YOUR_MEASUREMENT_ID>",
"CLIENT_ID": "<YOUR_CLIENT_ID>",
"FIREBASE_APP_ID": "<YOUR_FIREBASE_APP_ID>",
"APP_INSTANCE_ID": "<YOUR_APP_INSTANCE_ID>"}
<TRACKER>.create_new_event(name)
: See "Creating an Event" section below.<TRACKER>.send(events, validation_hit, postpone, date)
: Takes events
in the form of a list of dictionaries, then sends them as a POST request to GA4 or Firebase. validation_hit
defaults to False
and may be safely omitted; setting it to True
will send the hit to the validation domain. postpone
defaults to False
and may also be omitted; if you do not want to send the event immediately, setting postpone
to True
will enqueue the POST request. The optional date
field accepts a Python datetime option for sending historical hits up to 48 hours in the past. NOTE: if date
is specified, postpone
must be False
(the default value).<TRACKER>.postponed_send()
: Sends all enqueued POST requests (i.e., anything added via send(events, postpone=True)
), then empties the queue.<TRACKER>.append_event_to_params_dict(new_name_and_parameters)
: If necessary, add a new event and its expected parameters to the built-in utils.py
dictionary. new_name_and_parameters
takes a dictionary of with single key-value pair. Its key should be the new event name, and its value should be a list of parameters names (e.g., {'new_name': ['new_param_1', 'new_param_2', 'new_param_3']}
). NOTE: the utils.py
dictionary is used for error checking on automatically collected and recommended event types, and appending your own custom events is necessary only if you want them to be checked against the dictionary when using the send()
command.<GTAG_TRACKER>.random_client_id()
: If using the GtagMP
tracking object, this utility function will generate and return a new client ID matching the typical format of 10 random digits and the UNIX timestamp in seconds, joined by a period. This function will not overwrite the client ID on its own, but you may do so yourself using example_tracker.client_id = example_tracker.random_client_id()
.In order to solve questions around persistence, this library includes two options for storage:
DictStore
, a built-in dictionary class that will persist for the life of the tracking objectFileStore
, a built-in dictionary class that will read from and save to a JSON file in a specified locationUse of one of these two is required for session parameters (e.g., session_id
) and user properties, so initialization of the tracking object will also initialize a default DictStore
if a store object is not supplied as an argument.
In order to create your own store object, import either DictStore
or FileStore
from ga4mp.store
, and then use the new store object when initializing your tracker.
from ga4mp import GtagMP
from ga4mp.store import DictStore, FileStore
# DictStoreexpects a dict object
new_dict_store = DictStore(data=your_dictionary)
# FileStore expects a string pointing to a specific existing JSON file - or desired location and name of a new JSON file to be created automatically.
new_file_store = FileStore(data_location=".folder/file.json")
# Include whichever type of store you choose as an initialization argument for your tracker.
tracker = GtagMP(api_secret="934TXS", measurement_id="G-12345", client_id="1234852.1235081235", store=new_file_store)
<TRACKER>.store.save()
: Returns the current contents of the dictionary so that you can save them outside of the tracking object.<TRACKER>.store.save()
: Try to overwrite the JSON file at the data_location
given at time of store initialization with the current contents of the tracking object's dictionary.NOTE: The memory storage classes operate on 3 different types of data: user properties, which are sent to GA/Firebase with all events, session parameters, which should temporarily store information relevant to a single session (e.g., a session ID or the last time an event was sent), and other, for anything else you might want to save that wouldn't be sent to GA/Firebase.
Use one of the following to set a new value
with key name
as a user property, session parameter, or other type of stored data:
<TRACKER>.store.set_user_property(name, value)
<TRACKER>.store.set_session_parameter(name, value)
<TRACKER>.store.set_other_parameter(name, value)
Use one of the following to get the value of key name
for a user property, session parameter, or other type of stored data:
<TRACKER>.store.get_user_property(name)
<TRACKER>.store.get_session_parameter(name)
<TRACKER>.store.get_other_parameter(name)
Use one of the following to get all keys and values stored as a user property, session parameter, or other type of stored data:
<TRACKER>.store.get_all_user_properties()
<TRACKER>.store.get_all_session_parameters()
<TRACKER>.store.get_all_other_parameters()
Use one of the following to clear all keys and values stored as a user property, session parameter, or other type of stored data:
<TRACKER>.store.clear_user_properties()
<TRACKER>.store.clear_session_parameters()
<TRACKER>.store.clear_other_parameters()
While you may construct your own events and ecommerce items as dictionaries, the built-in Event and Item classes should eliminate guesswork about how to properly structure them.
To create an event, begin by using the following command from your tracking object:
<TRACKER>.create_new_event(name)
name
: Corresponds to the Event Name that you would want to see in your GA4/Firebase reporting. Per Google's requirements, Event Names must be 40 characters or fewer, may only contain alpha-numeric characters and underscores, and must start with an alphabetic character.The function will return an Event object with its own functions (see below). Once the Event is complete, you will be able to pass it to your tracking object's send()
function within a list of 1 or more events.
<EVENT>.set_event_name(name)
: Overwrite the current Event Name of the Event object with name
.<EVENT>.get_event_name()
: Return the current Event Name of the Event object.<EVENT>.set_event_param(name, value)
: Set a new value
with key name
as an Event parameter. If the key already exists, its value will be overwritten; otherwise, a new key-value pair will be added.<EVENT>.get_event_params()
: Return a dictionary of all parameters associated with the Event.<EVENT>.delete_event_param(name)
: Delete a single key-value pair with a key of name
from the Event's parameters.<EVENT>.create_new_item(item_id, item_name)
: See "Creating an Item" section below.<EVENT>.add_item_to_event(item)
: Add a single Item to the Event's items
list parameter. Note that item
is expected to be a single Item object or dictionary - not a list.While building an ecommerce event, create a new item by using the following command from your Event object: <EVENT>.create_new_item(item_id, item_name)
item_id
: The product SKU for the specific item.item_name
: The name for the specific item.At least one of item_id
or item_name
must be included; however, it is recommended to use both, if applicable.
The function will return an Item object with its own functions (see below). Once the Item is complete, you will be able to pass it to the associated Event object's add_item_to_event()
function.
<ITEM>.set_parameter(name, value)
: Set a new value
with key name
as an Item parameter.The following represents an example of building and sending a custom event to GA4:
from ga4mp import GtagMP
from ga4mp.store import DictStore
# Create a DictStore
my_store = DictStore(data=<DICTIONARY>)
# Create an instance of GA4 object using gtag, including the new DictStore.
gtag_tracker = GtagMP(api_secret=<API_SECRET>, measurement_id=<MEASUREMENT_ID>, client_id=<CLIENT_ID>, store=my_store)
# Create a new event for purchase.
purchase_event = gtag_tracker.create_new_event(name="purchase")
# Set transaction_id, value, and currency.
purchase_event.set_event_param(name="transaction_id", value="T_12345")
purchase_event.set_event_param(name="currency", value="USD")
purchase_event.set_event_param(name="value", value=12.21)
# Create an item and add details about the item.
shirt = purchase_event.create_new_item(item_id="SKU_12345", item_name="Stan and Friends Tee")
shirt.set_parameter("price", 9.99)
shirt.set_parameter("quantity", 1)
shirt.set_parameter("item_category", "Apparel")
# Add the item to the purchase event.
purchase_event.add_item_to_event(shirt)
# Add a user property based on what you know about the user.
gtag_tracker.store.set_user_property(name="shirt_wearer", value="yes")
# Send the event to GA4 immediately.
event_list = [purchase_event]
gtag_tracker.send(events=event_list)
Some relevant documentation from Google may be found below...
For more information on constructing events, please review the GA4 Measurement Protocol reference.
For more information on what user properties are in GA4 and what you can do with them, please review here
GA4 Measurement Protocol Support for Python is licensed under the BSD License.
FAQs
Google Analytics 4 Measurement Protocol Python Module
We found that ga4mp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.