Skip to main content

Event id

Event id should be a unique identifier of the event. By default it's a combination of:

  • user_pseudo_id (aka client_id)
  • event_timestamp
  • event_name
  • engagement_time_msec (if the event has this parameter)

But sometimes even this combination could be not unique. The main problem is that GA4 could send a few events in one bacth and event_timestamp isn't the time of the event but the time of the batch.

One way to guarantee uniqueness is to add a custom timestamp event parameter (for example gtm_event_timestamp) in your GTM setup. After that you could set timestampEventParamName property to use a custom event parameter as a part of event_id, like this:

const ga4 = require("dataform-ga4-sessions");// Define your configconst config = {  dataset: "analytics_XXXXXX",  incrementalTableName: "events_XXXXXX",};// Create event objectlet purchase = new ga4.Event(eventConfig);purchase.setEventName("purchase");purchase.timestampEventParamName = "gtm_event_timestamp";

Or you could set this property on EventFactory level to use it for all events:

const ga4 = require("dataform-ga4-sessions");// Define your configconst config = {  dataset: "analytics_XXXXXX",  incrementalTableName: "events_XXXXXX",};// Create event factory objectconst ef = new ga4.EventFactory(config);ef.timestampEventParamName = "gtm_event_timestamp";// Create all recommended form tracking eventslet pageView = ef.createPageView();
note

But if you use a custom timestamp event parameter, it is expected that it should be int_value. If it's for example string or float the package couldn't get this value.

Change event_id defenition#

To generate event_id by default the package uses getSqlEventId helper function.

But you could change the logic of event_id generation and provide your own SQL code, like this:

let ef = new ga4.EventFactory(config);let pageView = ef.createPageView();pageView.getSqlUniqueId = () => {  return `FARM_FINGERPRINT(CONCAT(event_timestamp, event_name, user_pseudo_id, ifnull((select ep.value.int_value from unnest(event_params) as ep where ep.key = 'engagement_time_msec' ),0))) as event_id`;};

Or you could create a unique event_id using your custom event_id set on GTM side. For example, if you added gtm_event_id event parameter, you could use it like this:

let ef = new ga4.EventFactory(config);let pageView = ef.createPageView();pageView.getSqlUniqueId = () => {  return `FARM_FINGERPRINT(CONCAT(event_timestamp, event_name, user_pseudo_id, ifnull((select ep.value.int_value from unnest(event_params) as ep where ep.key = 'gtm_event_id' ),0))) as event_id`;};

In this example we use not only gtm_event_id but other values (event_timestamp,event_name,user_pseudo_id) because auto generated events like session_start could miss your custom parameter or have the same initial value.

note

If you want to change event_id don't forget to add event_id alias ("as event_id" at the end) to your custom SQL code.

Delete events without event_id#

By default, the package deletes all events without event_id. And also publish method returns only one row for each event_id using QUALIFY:

QUALIFY ROW_NUMBER() OVER (PARTITION BY event_id) = 1

But you could change this behaviour by calling skipUniqueEventsStep() method on event object:

const ga4 = require("dataform-ga4-sessions");// Define your configconst config = {  dataset: "analytics_XXXXXX",  incrementalTableName: "events_XXXXXX",};// Create event objectlet purchase = new ga4.Event(eventConfig);purchase.setEventName("purchase");purchase.skipUniqueEventsStep();