Changelog
Unreleasedβ
π Premiumβ
- BigQuery utilities module
- Google Search Console module
π§° Coreβ
- nothing planned
π€ Communityβ
- nothing planned
Releasedβ
π [Premium v2.2.14]β
2026-10-01
π Fixedβ
- Google Ads campaign dates on new transfers (
google_ads_dim_campaigns) in the Google Ads module - Google Ads Data Transfers created after July 2026 no longer exportcampaign_start_date/campaign_end_date, which broke the build. The module now reads them when present and falls back to the date part ofcampaign_start_date_time/campaign_end_date_time, so older and newer transfers both work
Schema Changesβ
google_ads_dim_campaignsgainscampaign_start_date_timeandcampaign_end_date_time(DATETIME, account timezone) - rebuilt on the next run, no action
π [Premium v2.2.13]β
2026-09-16
π Addedβ
- Dimensions in every attribution report in the GA4 Attribution module - the configured
dimensions(and everyCUSTOM_CHANNEL_GROUPING) are now columns of all six report tables, not onlyga4_attribution_models. Each report carries one value per journey, so it stays additive; a new per-dimensionpick(firstdefault,last,min,max,chain) chooses which touch's value that is. See Dimensions & metrics - Attribution custom lineage in the GA4 Attribution module - two optional interception points,
custom_lineage.touchpoints_custom(between the touchpoints andga4_attribution_journeys: add offline touches withUNION ALL, drop Direct touches) andcustom_lineage.journeys_custom(between journeys and the models/reports: filter journeys, override journey columns). See Custom lineage - existing installs create the two template files by hand, the page has the code - Field dictionary (
ga4_attribution_field_dictionary) in the GA4 Attribution module - column name, type and description ofga4_attribution_modelsand the six reports, read fromINFORMATION_SCHEMAafter each rebuild, for a dashboard field glossary. See Output tables REFERRER_EXCLUDEin the GA4 module - GA4's "unwanted referrals": referrer hosts (payment providers, your own domains, tools) that never becomesource/mediumthrough thepage_referrerfallback. A session whose only referrer is excluded becomes direct, so the last non-direct lookback and the attribution touchpoints follow automatically. See Configuration- Cost monitoring across GCP projects (
monitored_projects) in the GCP Cost Monitoring module - list the projects (and optionally their region) whoseINFORMATION_SCHEMAthe module reads; each project keeps its own checkpoint, andgcp_cost_overviewgains aproject_idbreakdown with unchanged totals. See GCP Cost Monitoring
Changedβ
- Attribution report grain - with
dimensionsconfigured, each report's row grain includes the dimension columns. Totals per fixed key are unchanged; dashboards that group by the existing keys keep reporting the same figures - Agent skills cover the new options (attribution interception points,
pick,REFERRER_EXCLUDE, reprocessing after enabling it)
Schema Changesβ
- The six
ga4_attribution_*_reporttables gain one column per configured dimension / custom channel grouping (rebuilt on the next run - no action) gcp_cost_overviewgainsproject_id(rebuilt on the next run - no action)REFERRER_EXCLUDEneeds no schema change; history changes only after a reprocess ofga4_eventsonward for the range where the excluded referrer appeared
π [Premium v2.2.12]β
2026-08-31
π Addedβ
- GA4 Reporting module (
ga4_reporting_acquisition_report,ga4_reporting_conversion_rates_report,ga4_reporting_ecommerce_report,ga4_reporting_pages_report,ga4_reporting_consent_report,ga4_reporting_currency_rates,ga4_reporting_item_sales_report) - seven pre-aggregated, BI-ready report tables: acquisition/traffic with three attribution families side by side, session conversion rate per event, currency-aware daily ecommerce totals, page performance with entrances/exits, consent-mode analysis with extrapolated estimates, observed daily USD currency rates, and item-level sales. Event metric columns derive fromCUSTOM_SESSION_TOTALS; an optional dedicated dataset (REPORTING_DATASET_ENABLED/REPORTING_DATASET) lets you grant BI users access to reports only. See GA4 Reporting - USD values and refund columns in the item funnel (
ga4_item_funnel_sessions,ga4_item_funnel_report) - item revenue in USD plus refund metrics alongside the existing local-currency columns
Changedβ
- GA4 Event Conversion Rate module retired -
ga4_reporting_conversion_rates_reportis its successor (config moves toga4_reporting/config.yaml; the old report table is not deleted - drop it manually once dashboards are migrated). The old module'sis_new_sessiondrilldown was computed inverted; the new report fixes it, so new-vs-returning splits swap compared to old dashboards - Agent skills cover the reporting module - querying guidance (grains, non-summable columns, the ecommerce currency rule), run tags, reprocessing notes and the Premium feature guide
π Fixedβ
- Attribution compile error with session-only dimensions - with
touchpoint.mode: 'session'and a session-only custom dimension (e.g.session_source.term), the inactivesource_changefile failed the whole project compilation; the validation now only fires for the active mode
Schema Changesβ
ga4_sessionsgainstotals.sum.purchase_revenue_in_usd(new default session total, feeds the acquisition report'srevenue_in_usd). New STRUCT field: on existing installs, patch thetotalsschema or rebuildga4_sessions, then reprocess to backfill history - the ga4df-custom-params skill covers the procedurega4_eventsgains the top-levelevent_value_in_usdpassthrough (added automatically; historical rows stay NULL until reprocessed)
π οΈ [Installer v2.2.12]β
2026-08-31
π Addedβ
- Reporting dataset variables - Premium installs and updates seed
REPORTING_DATASET_ENABLED(off by default) andREPORTING_DATASET(name prepared up front) inworkflow_settings.yaml, so moving the GA4 Reporting tables to a dedicated dataset is a one-variable change; values you customize are preserved on update
π [Premium v2.2.11]β
2026-08-18
π Addedβ
- Single-touch splits (
ga4_attribution_channel_assist_report) in the GA4 Attribution module -single_touch_journeys,closed_single_touch_journeysandsingle_touch_revenueseparate journeys where a channel was the only touch, and new additive sums (sum_traffic_touches,sum_journey_length_days,sum_days_to_conversion) let dashboards derive average path length and average days to conversion per channel. See Output Tables - With-vs-without comparison (
ga4_attribution_micro_conversion_report) in the GA4 Attribution module - newjourneys_without,closed_journeys_without,closing_conversion_count_withoutandclosing_revenue_withoutcolumns quantify a micro-conversion's lift on final outcomes from a single table;with + withoutties back to the total journey count, and every configured micro-conversion now appears on every journey date (zero-filled when it did not fire) - Column descriptions from config in the GA4 Attribution module - config-driven columns (extra
dimensions,metrics, custom channel groupings) now get BigQuery column descriptions automatically, taken from the upstream GA4 column docs or an optionaldescriptionkey on the config entry - Compile-time config validation in the GA4 Attribution module - invalid dimension paths (e.g. a
ga4_sessions-only field insource_changemode) now fail at compile time with an actionable message instead of erroring mid-run
Changedβ
- Sharper agent skills - the side-effecting skills (reprocessing, custom params, custom models, managing runs, upgrade) end with checkable "Done when" criteria so a half-finished procedure is not reported as done; the onboarding skill was restructured for reliability; the agent guides (
AGENTS.md/CLAUDE.md/GEMINI.md) gained a Language section disambiguating the product terms that get mixed up (reprocess vs rebuild, managed vs custom, release vs workflow, ...), andMY-COMPANY.mdgained an "Our vocabulary" section for your own terms rebuild_schedulesemantics documented in the GA4 Attribution module - the cron gate is evaluated when the Dataform release compiles, not when the workflow executes, so the release must recompile at least as often as the schedule needs to take effect. The config comment and docs now spell this out
π Fixedβ
All in the GA4 Attribution module, from a full correctness review:
- Dates near midnight - journey and model dates were derived in UTC while the rest of the module uses
LOCAL_TIMEZONE; touches near midnight landed in the wrong partition - Micro-conversion "without" denominators - the
*_withoutcolumns only covered dates a micro-conversion fired on, understating them for anything that does not fire daily; they now cover every journey date - Journey boundaries -
inactivity_gap_daysis now measured in fractional days (a 47-hour gap trips a 1-day boundary),pre_conversion_lookback_daysno longer shatters older touches into single-touch journeys, and an abandoned journey now lapses via the inactivity gap instead of staying open forever - Credit edge cases -
position_basedwith both weights 0 dropped the conversion's credit on 2-touch journeys (now splits 50/50, and 2-touch renormalization follows the configured weights); credit is summed at full float precision and rounded once - Touch ordering and source propagation - a conversion on a session's first event no longer ties ahead of its own traffic touch, and a conversion event's traffic source now reaches the rest of its session
- Smaller fixes - zero-touch journeys report
path_length0 (was 1), a duplicatelabs.perplexity.aisource-category row fanned out touches on the LIKE join, the conversion-lag<= 30bucket boundary, and NULL dimensions normalize to'(not set)'/ ongoing journeys to'(no conversion)'
Schema Changesβ
- New columns on
ga4_attribution_channel_assist_reportandga4_attribution_micro_conversion_report. Attribution tables are rebuilt on the module'srebuild_schedule(default: every run), so the columns appear after the next scheduled rebuild - no manual action needed
π [Premium v2.2.10]β
2026-08-04
π Addedβ
- Agent skills - every installation now ships ten task-specific skills your AI assistant loads on demand, in two identical copies:
.claude/skills/(Claude Code, Cursor) and.agents/skills/(Codex CLI, Gemini CLI). They cover setup (ga4df-onboarding), querying, pipeline debugging, custom parameters, custom models, reprocessing and backfills, running the pipeline, the CoreβPremium upgrade, cost monitoring, and writing your own skills. Ask in plain language - "backfill last March", "why is today missing", "add a custom event parameter" - and the assistant follows the product's own procedure instead of improvising. See Agent Skills and Onboarding with an AI Agent - Bundled scripts the assistant (or you) can run directly:
patch_struct_schema.shadjusts a BigQuery STRUCT column so a new custom parameter can be added without a full rebuild,recompile_release.pyrecompiles the release configuration from the CLI, andpush_dataform_workspace.pypushes a local copy of the workspace back through the Dataform API - Setup reference guides the assistant consults before changing configuration: a full
ga4module option reference (every option, its default, whether it needs a schema patch, and what changing it does to history), an attribution setup guide, and a Cloud Storage export setup guide
Changedβ
- Core config arrays now ship empty in the GA4 Attribution module (
conversions,attribution_models,touchpoint.source_change_unique_fields) and the Google Ads module (conversion_action_names). Array entries in a core config merge into every installation and cannot be removed from your own config file, so the starter entries now live in your editable copy underincludes/custom/modules/<module>/where you can trim or replace them batch-reprocess.shis safer - it validates its inputs, prints the batch plan and asks for confirmation before running anything (--yesskips the prompt for non-interactive use), stops on the first failed batch and prints the exact command to resume from there. Default tags now includetransactions
π Fixedβ
- Parameter Detection first build -
ga4_parameter_detection_report_dailyfailed to compile on a first (non-incremental) build when compiling with the Dataform CLI; compilations in the Dataform interface were unaffected. The module now builds from scratch either way
π οΈ [Installer v2.2.11]β
2026-08-04
π Addedβ
- Agent skill installation - new installations and package updates now deliver the agent skills that ship with Premium v2.2.10+
π [Premium v2.2.9]β
2026-07-10
π Addedβ
- AI-ready workspace - every installation now ships context files for AI agents:
AGENTS.md/CLAUDE.md/GEMINI.md(one agent guide, three standard filenames),LINEAGE.md(every table's grain, upstream sources and downstream consumers) andMY-COMPANY.md(a business-context template you fill in once; preserved across updates). Point Gemini, Claude, Cursor or any coding agent at your Dataform workspace and it knows the boundaries, the data model and your business. See AI-Ready Workspace - Source group column (
source_group) in the GA4 module - opt-in consolidation of the many source spellings of common platforms (Facebook, Instagram, TikTok, Bing, AI assistants like ChatGPT and Perplexity, ...) into one clean label, added insidefixed_traffic_source(ga4_events) andsession_source/last_non_direct_traffic_source(ga4_sessions). Enable withADD_SOURCE_GROUP_COLUMN, customize viaSOURCE_GROUP_ARRAY. See GA4 Configuration - Attribution rebuild schedule (
rebuild_schedule) in the GA4 Attribution module - a 3-field cron expression that gates the rebuild layer (journeys, models and all reports) to cut cost, e.g."* * 1"rebuilds Mondays only. Touchpoint tables keep running incrementally every execution. Default"* * *"(rebuild on every run). See Attribution Configuration event_original_occurrence_timestamponga4_events- new GA4 export field passed through: for late-arriving events processed after the 72h window (e.g. SDK events), it preserves when the event originally occurred on the device, whileevent_date/event_timestampreflect processing time
Changedβ
- Self-describing tables - every output table's BigQuery description now states its grain ("1 row per ..."), and every transformation CTE carries a purpose comment; column descriptions across the documentation set were rewritten for clarity. Helps humans and AI agents alike
Schema Changesβ
event_original_occurrence_timestamp(top-level,ga4_events) is added automatically on the next incremental run; historical dates stayNULLuntil reprocessedsource_groupis added inside existing STRUCT columns whenADD_SOURCE_GROUP_COLUMNis enabled - on an existing installation this requires a schema adjustment or table rebuild, plus a reprocess to backfill history
π οΈ [Installer v2.2.10]β
2026-07-10
π Addedβ
MY-COMPANY.mdpreserved on updates - the business-context template ships with Premium v2.2.9 and is created when missing, but once you've filled it in, package updates never overwrite it (same guarantee asdefinitions/custom/andincludes/custom/)
π [Premium v2.2.8]β
2026-06-22
π Addedβ
- GA4 Attribution Modeling module - multi-touch attribution from raw GA4 events: a touchpoint stream (session or source_change mode) is grouped into user journeys, conversion credit is apportioned across touches by fractional models (first-touch, last-touch, linear, position-based, time-decay) plus an opt-in participation model, and six additive, date-partitioned reports cover channel chains, journey summaries, channel assists, channel transitions (Sankey), conversion lag, and micro-conversion lift. Opt-in (
enabled: false); define your conversions andjourney.closing_conversionsto populate it. See GA4 Attribution Modeling GA4_DATASET_PROJECT- read the GA4 export from a different GCP project than the one your outputs are written to (e.g. a dev/test project reading the production export). Setvars.GA4_DATASET_PROJECTinworkflow_settings.yaml; defaults to the output project when unset. The Dataform service account needs BigQuery Data Viewer on the source dataset. See Cross-Project Setup
π οΈ [Installer v2.2.8]β
2026-06-16
π Fixedβ
- Preserve customer GitHub connection on Dataform repo updates - repo updates no longer reconcile away a customer's out-of-band GitHub connection. The Dataform repository's externally-managed
git_remote_settings(and workspace compilation overrides) are now left untouched on refresh, so the GitHub remote stays connected and workspaces no longer end up in a conflicted git state
π [Premium v2.2.7]β
2026-06-15
π Fixedβ
- Custom lineage views skipped when the step is disabled - the custom GA4 lineage actions (
ga4_events_custom,int_ga4_sessions_custom,ga4_sessions_custom) are no longer materialized as orphan pass-through views whenCUSTOM_LINEAGE.<table>isfalse; downstream tables already read the core tables directly in that case is_finaltimezone fix - the data-finality flag now computesCURRENT_DATE()in the install'sLOCAL_TIMEZONEinstead of timezone-naive UTC, so the 72-hour late-data window flips on the correct day boundary for the data
π [Premium v2.2.6]β
2026-06-11
π Addedβ
- Export to Google Cloud Storage - opt-in cross-cloud export that writes your output tables to a GCS bucket as partitioned Parquet, ready to load into Snowflake, Databricks, BigLake, or any Parquet-aware engine. Off by default; enable it globally with the
GCS_EXPORT_*settings inworkflow_settings.yamlor per-module with aGCS_EXPORToverride. Partitioned tables are written as hive-partitioned folders (one file set per date), incremental tables export only the current load window, and the export runs as a best-effort step that never fails the table build. See Export to Google Cloud Storage - Open-text SQL filter (
sql) forCUSTOM_SESSION_PARAMS_ARRAYandCUSTOM_SESSION_TOTALSin the GA4 module - a raw SQL boolean predicate as an escape hatch wheneventFilter/paramFiltercan't express the condition (e.g. matching onpage.path). Mutually exclusive witheventFilter/paramFilter; foreventsToCountasqlentry must also setrenameTo fallbackFieldfor custom channel grouping in the GA4 module - choose which default field unmatched traffic falls back to whenuseDefaultChannelGroupingAsFallback: true(defaults todefault_channel_grouping)
Changedβ
- Empty default
conversion_action_namesin the Google Ads module - the default config now ships an empty list instead of thePurchase/Add to Cart/30s on pageplaceholders; define your own conversion actions in the custom config. Existing installs keep their configured values - Empty default
listAttributiondimensions in the Item Funnel module -dimsToStoreandpickDimsFromTheseEventsnow ship empty by default; populate them in the custom config to enable item list attribution
π οΈ [Installer v2.2.7]β
2026-06-07
π Addedβ
- VPC Service Controls warning - the installer now detects when VPC Service Controls are active on the project and surfaces a warning during setup, so you can resolve access restrictions before they cause silent failures
- Billing warning - the installer now surfaces a warning when billing configuration may affect the deployment, reducing ambiguity during first-time setups
π [Premium v2.2.5]β
2026-06-07
π Addedβ
- Brave classified as a search engine in source categories β sessions originating from Brave Search are now correctly attributed to Organic Search in the default channel grouping
- Improved AI referrer classification β ChatGPT and Perplexity are now classified more accurately in the default channel grouping, reducing misattribution to direct or referral
π Fixedβ
fixed_traffic_sourceattribution fix β the GA4 BigQuery export can deliver hits out of order: a hit with an earlier timestamp may arrive in a later batch and therefore lackcollected_traffic_source. The previous logic selected the earliest hit, which could be one of those under-informed hits, causing sessions to show incorrect or missing traffic source data. Source derivation now selects the hit with the most information, and cases where timestamp and batch ordering disagree are handled correctly. Multi-source sessions now derive the last source only from hits that havecollected_traffic_sourceset. This resolves incorrect Referral classification for some Organic sources, including gclid traffic without a campaign appearing as Google Referral.
π [Premium v2.2.4]β
2026-04-28
π Addedβ
all_conversionsandall_conversions_valuein the Google Ads module - aggregate ofmetrics_conversionsandmetrics_conversions_valueacross all configuredconversion_action_names, added togoogle_ads_campaign_report,google_ads_ad_group_report,google_ads_ad_report, andgoogle_ads_keyword_report. Provides a stable column name for downstream dashboards regardless of which individual conversion actions are configuredaddDefaultflag forCUSTOM_SESSION_TOTALSin the GA4 module - whentrue, merges a curated baseline ofeventsToCount,uniqueFields, andsumFields(page_view, session_start, ecommerce events, transaction_id, user_id, device.category, page hostname/path, engagement_time_msec, purchase_revenue) with your custom entries (your entries win onrenameTo/namecollision). Defaults totruefor new installs; existing installs without the flag continue to see only their explicitly configured entriesonSchemaChange: EXTENDongoogle_ads_dim_ad_groups,google_ads_dim_ads,google_ads_dim_keywords, andgoogle_ads_gclids- column additions in future releases no longer require a rebuild
π Fixedβ
- Apostrophes and other special characters in Google Ads
conversion_action_names(e.g.Client's Call) now work - conversion action names are wrapped in BigQuery triple-quoted string literals so escaping no longer breaks Dataform's compile pipeline - Clearer error messages for Google Ads misconfigurations - separate, actionable errors when
enabled: truebutgads_sourcesis missing/empty/malformed, whenconversion_action_namesis missing/empty/malformed, and whenenabled: falsebutgads_sourcescontains entries - Generic config merge now concatenates and dedupes arrays (by
renameTo/name/value, custom wins) instead of replacing whole arrays - lets core ship baseline arrays users can extend without redeclaring
Schema Changesβ
This release introduces new columns on Google Ads report tables (all_conversions, all_conversions_value). Thanks to onSchemaChange: EXTEND no rebuild is required, but historical values for these columns will only populate from this version forward. Run a reprocessing job over the desired date range if you need them backfilled.
For CUSTOM_SESSION_TOTALS, existing installs see no schema change unless they explicitly opt in by setting addDefault: true in includes/custom/modules/ga4/config.js.
π οΈ [Installer v2.2.2]β
2026-04-08
π Addedβ
- Automated GA4 Export Trigger - automatically update your GA4 output tables the moment the GA4 daily events export lands in BigQuery (Premium π)
- Email Alerts for Dataform Errors - get notified by email when a Dataform workflow invocation fails (Premium π)
π [Premium v2.2.3]β
2026-04-08
π Addedβ
- Custom Lineage (
ga4_events_custom,int_ga4_sessions_custom,ga4_sessions_custom) in the GA4 module - inject custom transformation layers between core pipeline tables as views or incremental tables, with automatic routing for all downstream modules - Reprocessing & Batching - reprocess specific date ranges without rebuilding entire history, with a batch script (
scripts/batch-reprocess.sh) for large backfills that avoids BigQuery's 6-hour timeout - PII Detection in the Parameter Detection module - automatically detects personally identifiable information in parameter names and values, with 19 configurable value patterns and a pattern tester view
- Multi-property support in the Parameter Detection module -
property_idandproperty_namecolumns in all output tables for per-property parameter auditing paramFilterfor Session Totals -eventsToCount,uniqueFields, andsumFieldsinCUSTOM_SESSION_TOTALSnow support the sameparamFiltersyntax asCUSTOM_SESSION_PARAMS_ARRAYfor conditional aggregation
π Fixedβ
ignore_referrercase sensitivity - now correctly matches GA4's lowercase"true"value- Medium attribution
CASEreordering to prevent misclassification - Module dependency resolution when a module config is disabled
ref()resolution for disabled modules
Schema Changesβ
Updating to this version adds property_id and property_name columns to ga4_parameter_detection_report_daily via onSchemaChange: EXTEND. No full rebuild is required, but if you need historical values for these fields you will need to rebuild the table.