In the GA4 BigQuery export, the event_params repeated field looks like the gateway to every custom dimension. The usual first move is to UNNEST() it, along with everything else, into one wide table. That is intuitive, and it is a frequent cause of badly wrong results.
Each event row mixes several scopes. Parameters in event_params such as page_location or transaction_id describe the event itself. user_properties, a separate repeated field, records attributes of the user as they stood when the event fired. The items array, populated on ecommerce events, holds one entry per product. Sessions have no table of their own: the session key is user_pseudo_id combined with the ga_session_id event parameter, and every session-level attribute has to be derived from the events within it. Unnesting all of this in one pass conflates different grains.
Mixed grains produce aggregations that are subtly or plainly wrong. A user property repeated on every event is counted once per event rather than once per user. A user's first acquisition source is credited only to the event where it appeared, instead of being carried to the user's later actions. Joining item_id to session-level attributes without first aggregating items to the session inflates session metrics. Reporting built on this foundation has produced wrong LTV figures and attribution models, and A/B test readouts based on duplicated rows.
A dbt project with explicit staging layers prevents this. Instead of one monolithic UNNEST: first extract user_properties into a separate model or CTE keyed on user_pseudo_id; then extract items into an item-grain model; then flatten the remaining event-scoped parameters; and only then aggregate to session and user grain before any cross-scope join. Every model has a declared grain, and a session model keyed on user_pseudo_id and ga_session_id holds exactly one row per session. Privacy-first collection tools such as Robin Signals call for the same discipline, since they require an explicit schema and clear data intent from the start.
With each dimension modelled at its natural scope, funnel analysis, segmentation by persistent user attributes, LTV models and experiment analysis all start from correct counts. This scope work is what makes later statistical modelling and causal inference defensible.
Viktor Kvant
Senior Web Analyst specialising in data ownership, advanced tracking implementations, and translating data into strategic business value.
Connect on LinkedIn