ga4-export-fixer 0.9.0-dev.13 → 0.9.0-dev.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/helpers/ga4Transforms.js
CHANGED
|
@@ -235,9 +235,11 @@ const itemListAttributionExpr = (lookbackType, timestampColumn, lookbackTimeMs)
|
|
|
235
235
|
frameBounds = `range between ${lookbackMicros} preceding and current row`;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
//
|
|
239
|
-
//
|
|
240
|
-
|
|
238
|
+
// Suppress attribution for:
|
|
239
|
+
// - refund events (outside the selection-driven journey window)
|
|
240
|
+
// - unconsented events (user_pseudo_id is NULL) — attribution requires a visitor
|
|
241
|
+
// identity to stitch select_* events to later receivers within the same visitor.
|
|
242
|
+
return `if(event_name = 'refund' or user_pseudo_id is null, null, last_value(
|
|
241
243
|
if(${selectEvents}, ${structExpr}, null) ignore nulls
|
|
242
244
|
) over(
|
|
243
245
|
partition by ${partitionBy}
|
|
@@ -260,6 +262,10 @@ const itemListAttributionExpr = (lookbackType, timestampColumn, lookbackTimeMs)
|
|
|
260
262
|
* the rows are interchangeable, so arbitrary row number assignment between them
|
|
261
263
|
* produces the same result.
|
|
262
264
|
*
|
|
265
|
+
* Unconsented events (user_pseudo_id is NULL) use an empty-string sentinel inside
|
|
266
|
+
* concat — without it, CONCAT NULL-propagates and the row_id becomes NULL, which
|
|
267
|
+
* would prevent enrichments from applying to such events.
|
|
268
|
+
*
|
|
263
269
|
* @param {string} ecommerceEventsFilter - Comma-separated, quoted list of event names
|
|
264
270
|
* (e.g., "'purchase', 'add_to_cart'").
|
|
265
271
|
* @returns {string} SQL expression that evaluates to the row id or NULL.
|
|
@@ -268,7 +274,7 @@ const itemRowId = (ecommerceEventsFilter) => {
|
|
|
268
274
|
return `if(
|
|
269
275
|
event_name in (${ecommerceEventsFilter}),
|
|
270
276
|
farm_fingerprint(concat(
|
|
271
|
-
user_pseudo_id,
|
|
277
|
+
ifnull(user_pseudo_id, ''),
|
|
272
278
|
cast(event_timestamp as string),
|
|
273
279
|
event_name,
|
|
274
280
|
to_json_string(items),
|
package/package.json
CHANGED
|
@@ -414,10 +414,13 @@ ${excludedEventsSQL}`,
|
|
|
414
414
|
|
|
415
415
|
const finalColumnOrder = getFinalColumnOrder(eventDataStep, sessionDataStep);
|
|
416
416
|
|
|
417
|
-
// When the items scaffold is active, override the items column and exclude _item_row_id
|
|
418
|
-
//
|
|
417
|
+
// When the items scaffold is active, override the items column and exclude _item_row_id.
|
|
418
|
+
// ifnull(..., []) preserves the empty-array shape for events that have no items_rebuilt
|
|
419
|
+
// match (non-ecommerce events, or ecommerce events with empty items arrays). The empty
|
|
420
|
+
// array literal is type-inferred from items_rebuilt.items, which includes any item-level
|
|
421
|
+
// enrichment columns — so additive enrichments don't cause a struct-schema mismatch.
|
|
419
422
|
const itemListOverrides = itemListSteps ? {
|
|
420
|
-
items: '
|
|
423
|
+
items: 'ifnull(items_rebuilt.items, [])',
|
|
421
424
|
} : {};
|
|
422
425
|
const itemListExcludedColumns = itemListSteps ? ['_item_row_id'] : [];
|
|
423
426
|
|