ga4-export-fixer 0.5.2-dev.3 → 0.5.2-dev.4
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/package.json
CHANGED
|
@@ -161,6 +161,9 @@ const _generateEnhancedEventsSQL = (mergedConfig) => {
|
|
|
161
161
|
|
|
162
162
|
// item list attribution config
|
|
163
163
|
const itemListAttribution = mergedConfig.itemListAttribution;
|
|
164
|
+
const ecommerceEventsFilter = itemListAttribution
|
|
165
|
+
? helpers.ga4EcommerceEvents.filter(e => e !== 'refund').map(e => `'${e}'`).join(', ')
|
|
166
|
+
: null;
|
|
164
167
|
|
|
165
168
|
// auto-adjust bufferDays for time-based item list attribution lookback
|
|
166
169
|
const effectiveBufferDays = (itemListAttribution && itemListAttribution.lookbackType === 'TIME')
|
|
@@ -225,11 +228,12 @@ const _generateEnhancedEventsSQL = (mergedConfig) => {
|
|
|
225
228
|
// ecommerce
|
|
226
229
|
ecommerce: helpers.fixEcommerceStruct('ecommerce'),
|
|
227
230
|
items: 'items',
|
|
228
|
-
// unique row id for item list attribution join.
|
|
229
|
-
// row_number()
|
|
231
|
+
// unique row id for item list attribution join. Only computed for ecommerce events.
|
|
232
|
+
// row_number() breaks hash collisions for batched events with identical data.
|
|
233
|
+
// partition by event_name avoids a single-partition bottleneck in the window function.
|
|
230
234
|
// Non-determinism is safe: colliding rows have identical items (to_json_string(items) is in the hash),
|
|
231
235
|
// so swapping row numbers between them produces the same final result.
|
|
232
|
-
|
|
236
|
+
_item_list_attribution_row_id: itemListAttribution ? `if(event_name in (${ecommerceEventsFilter}), farm_fingerprint(concat(user_pseudo_id, cast(event_timestamp as string), event_name, to_json_string(items), cast(row_number() over(partition by event_name, user_pseudo_id) as string))), null)` : undefined,
|
|
233
237
|
// flag if the data is "final" and is not expected to change anymore
|
|
234
238
|
data_is_final: helpers.isFinalData(mergedConfig.dataIsFinal.detectionMethod, mergedConfig.dataIsFinal.dayThreshold),
|
|
235
239
|
export_type: helpers.getGa4ExportType('_table_suffix'),
|
|
@@ -272,12 +276,11 @@ ${excludedEventsSQL}`,
|
|
|
272
276
|
itemListAttribution.lookbackTimeMs
|
|
273
277
|
);
|
|
274
278
|
const passthroughEvents = `event_name in ('view_item_list', 'select_item', 'view_promotion', 'select_promotion')`;
|
|
275
|
-
const ecommerceFilter = helpers.ga4EcommerceEvents.filter(e => e !== 'refund').map(e => `'${e}'`).join(', ');
|
|
276
279
|
|
|
277
280
|
return {
|
|
278
281
|
name: 'item_list_data',
|
|
279
282
|
columns: {
|
|
280
|
-
'
|
|
283
|
+
'_item_list_attribution_row_id': '_item_list_attribution_row_id',
|
|
281
284
|
'items': `array_agg(
|
|
282
285
|
(select as struct item.* replace(
|
|
283
286
|
coalesce(if(${passthroughEvents}, item.item_list_name, _item_list_attr.item_list_name), '(not set)') as item_list_name,
|
|
@@ -286,19 +289,19 @@ ${excludedEventsSQL}`,
|
|
|
286
289
|
))
|
|
287
290
|
)`,
|
|
288
291
|
},
|
|
289
|
-
from: `(select
|
|
290
|
-
groupBy: ['
|
|
292
|
+
from: `(select _item_list_attribution_row_id, event_name, item, ${attrExpr} as _item_list_attr from event_data, unnest(items) as item where event_name in (${ecommerceEventsFilter}))`,
|
|
293
|
+
groupBy: ['_item_list_attribution_row_id'],
|
|
291
294
|
};
|
|
292
295
|
})() : null;
|
|
293
296
|
|
|
294
297
|
const finalColumnOrder = getFinalColumnOrder(eventDataStep, sessionDataStep);
|
|
295
298
|
|
|
296
|
-
// When item list attribution is enabled, override the items column and exclude
|
|
299
|
+
// When item list attribution is enabled, override the items column and exclude _item_list_attribution_row_id
|
|
297
300
|
// COALESCE handles events without items (not in ecommerce filter) where the LEFT JOIN returns NULL
|
|
298
301
|
const itemListOverrides = itemListDataStep ? {
|
|
299
302
|
items: 'coalesce(item_list_data.items, event_data.items)',
|
|
300
303
|
} : {};
|
|
301
|
-
const itemListExcludedColumns = itemListDataStep ? ['
|
|
304
|
+
const itemListExcludedColumns = itemListDataStep ? ['_item_list_attribution_row_id'] : [];
|
|
302
305
|
|
|
303
306
|
// Join event_data and session_data, include additional logic
|
|
304
307
|
const finalStep = {
|
|
@@ -334,7 +337,7 @@ ${excludedEventsSQL}`,
|
|
|
334
337
|
leftJoin: [
|
|
335
338
|
...(itemListDataStep ? [{
|
|
336
339
|
table: 'item_list_data',
|
|
337
|
-
condition: 'using(
|
|
340
|
+
condition: 'using(_item_list_attribution_row_id)'
|
|
338
341
|
}] : []),
|
|
339
342
|
{
|
|
340
343
|
table: 'session_data',
|