This workflow corresponds to n8n.io template #11010 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "JA9djpPUOUCsIR6e",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "GA4-to-BigQuery-Backfill",
"tags": [],
"nodes": [
{
"id": "de9827c8-f389-4ddd-82fc-af6df83c11be",
"name": "GA4 - Session Channel Group",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
-32
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{
"listName": "sessions"
},
{},
{
"name": "=newUsers",
"listName": "other"
},
{
"name": "=ecommercePurchases",
"listName": "other"
},
{
"name": "=purchaseRevenue",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"name": "=sessionDefaultChannelGroup",
"listName": "other"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "9cac6be1-4782-4bf7-b35c-65a265a43270",
"name": "BQ - ga4_data_session_channel_group",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
-32
],
"parameters": {
"options": {},
"sqlQuery": "-- This query creates a table for session data by channel group for the specified date range.\n-- It then inserts the aggregated data from the corresponding GA4 node.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_session_channel_group_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n sessionDefaultChannelGroup STRING,\n sessions INT64,\n totalUsers INT64,\n newUsers INT64,\n ecommercePurchases INT64,\n purchaseRevenue FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_session_channel_group_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, sessionDefaultChannelGroup, sessions, totalUsers, newUsers, ecommercePurchases, purchaseRevenue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'}, ${row.metricValues[4].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "0521bcf3-a478-476e-b600-c78e9e51be41",
"name": "GA4 - Session Source/Campaign/Medium",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
160
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{
"listName": "sessions"
},
{},
{
"name": "=newUsers",
"listName": "other"
},
{
"name": "=ecommercePurchases",
"listName": "other"
},
{
"name": "=purchaseRevenue",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"name": "=sessionSource",
"listName": "other"
},
{
"name": "=sessionCampaignName",
"listName": "other"
},
{
"name": "=sessionMedium",
"listName": "other"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "efb72346-baff-42d4-82ae-31167c3f9773",
"name": "BQ - ga4_data_session_source_campaign_medium",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
160
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily table for session data by source, campaign, and medium.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_session_source_campaign_medium_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n sessionSource STRING,\n sessionCampaignName STRING,\n sessionMedium STRING,\n sessions INT64,\n totalUsers INT64,\n newUsers INT64,\n ecommercePurchases INT64,\n purchaseRevenue FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_session_source_campaign_medium_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }}(date, sessionSource, sessionCampaignName, sessionMedium, sessions, totalUsers, newUsers, ecommercePurchases, purchaseRevenue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', '${row.dimensionValues[2].value}', '${row.dimensionValues[3].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'}, ${row.metricValues[4].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"executeOnce": false,
"typeVersion": 2.1
},
{
"id": "04c362d9-7678-4110-a65a-5b6b5af27200",
"name": "GA4 - Country/Language/City",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
352
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{
"listName": "sessions"
},
{
"listName": "screenPageViews"
},
{},
{
"name": "=newUsers",
"listName": "other"
},
{
"name": "=ecommercePurchases",
"listName": "other"
},
{
"name": "=purchaseRevenue",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"listName": "city"
},
{
"listName": "language"
},
{
"listName": "country"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "f67555ea-ccd9-41fe-a118-f47954d60e42",
"name": "BQ - ga4_data_country_language_city",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
352
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily table for user data by country, language, and city.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_country_language_city_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n country STRING,\n language STRING,\n city STRING,\n sessions INT64,\n screenPageViews INT64,\n totalUsers INT64,\n newUsers INT64,\n ecommercePurchases INT64,\n purchaseRevenue FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_country_language_city_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, country, language, city, sessions, screenPageViews, totalUsers, newUsers, ecommercePurchases, purchaseRevenue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', '${row.dimensionValues[2].value}', '${row.dimensionValues[3].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'}, ${row.metricValues[4].value || 'NULL'}, ${row.metricValues[5].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "9061c72d-e67d-4761-a730-f024294d8645",
"name": "GA4 - Item Name",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
544
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{
"name": "=itemPurchaseQuantity",
"listName": "other"
},
{
"name": "=itemRevenue",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"listName": "itemName"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "f3d2ecf5-fcce-421e-bd5f-1d5380969661",
"name": "BQ - ga4_data_item_name",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
544
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily table for item-specific metrics.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_item_name_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n itemName STRING,\n itemPurchaseQuantity INT64,\n itemRevenue FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_item_name_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }}(date, itemName, itemPurchaseQuantity, itemRevenue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "0c380ced-0dd0-4c17-ada9-3a31cc83d817",
"name": "GA4 - Browser/OS/Device",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
736
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{
"listName": "sessions"
},
{},
{
"listName": "screenPageViews"
},
{
"name": "=newUsers",
"listName": "other"
},
{
"name": "=ecommercePurchases",
"listName": "other"
},
{
"name": "=purchaseRevenue",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"listName": "browser"
},
{
"name": "=operatingSystem",
"listName": "other"
},
{
"listName": "deviceCategory"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "7d699fd6-5ba7-4675-b4ba-abb4eb76df57",
"name": "BQ - ga4_data_browser_os_device",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
736
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily table for technology data (browser, OS, device).\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_browser_os_device_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n browser STRING,\n operatingSystem STRING,\n deviceCategory STRING,\n sessions INT64,\n screenPageViews INT64,\n totalUsers INT64,\n newUsers INT64,\n ecommercePurchases INT64,\n purchaseRevenue FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_browser_os_device_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, browser, operatingSystem, deviceCategory, sessions, screenPageViews, totalUsers, newUsers, ecommercePurchases, purchaseRevenue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', '${row.dimensionValues[2].value}', '${row.dimensionValues[3].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'}, ${row.metricValues[4].value || 'NULL'}, ${row.metricValues[5].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"retryOnFail": false,
"typeVersion": 2.1
},
{
"id": "839aab16-0b61-438d-a8be-daa1dcf0de38",
"name": "GA4 - First User Source/Medium",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
928
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{},
{
"name": "=newUsers",
"listName": "other"
},
{
"name": "=ecommercePurchases",
"listName": "other"
},
{
"name": "=purchaseRevenue",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"name": "=firstUserMedium",
"listName": "other"
},
{
"name": "=firstUserCampaignName",
"listName": "other"
},
{
"name": "=firstUserSource",
"listName": "other"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "58ac9920-db2c-4bb0-9ac5-a0c3395fa435",
"name": "BQ - ga4_data_first_user_source_medium",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
928
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily table for first-user acquisition source.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_first_user_source_medium_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n firstUserMedium STRING,\n firstUserSource STRING,\n firstUserCampaignName STRING,\n totalUsers INT64,\n newUsers INT64,\n ecommercePurchases INT64,\n purchaseRevenue FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_first_user_source_medium_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, firstUserMedium, firstUserSource, firstUserCampaignName, totalUsers, newUsers, ecommercePurchases, purchaseRevenue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', '${row.dimensionValues[2].value}', '${row.dimensionValues[3].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "9dabc1ce-2e6e-4f1d-b849-45d69d9e36a2",
"name": "GA4 - First User Channel Group",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
1120
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{},
{
"name": "=newUsers",
"listName": "other"
},
{
"name": "=ecommercePurchases",
"listName": "other"
},
{
"name": "=purchaseRevenue",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"name": "=firstUserDefaultChannelGroup",
"listName": "other"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "5f351870-d30e-4bbd-a424-4d2909c69e83",
"name": "BQ - ga4_data_first_user_channel_group",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
1120
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily table for first-user acquisition by channel group.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_first_user_channel_group_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n firstUserDefaultChannelGroup STRING,\n totalUsers INT64,\n newUsers INT64,\n ecommercePurchases INT64,\n purchaseRevenue FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_data_first_user_channel_group_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, firstUserDefaultChannelGroup, totalUsers, newUsers, ecommercePurchases, purchaseRevenue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "c36e4a29-f8a0-4ba5-9bd2-f42621935ca5",
"name": "GA4 - Ads Data",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
1312
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{
"name": "=ecommercePurchases",
"listName": "other"
},
{
"name": "=averagePurchaseRevenue",
"listName": "other"
},
{
"name": "=purchaseRevenue",
"listName": "other"
},
{
"name": "=advertiserAdClicks",
"listName": "other"
},
{
"name": "=advertiserAdCost",
"listName": "other"
},
{
"name": "=advertiserAdCostPerClick",
"listName": "other"
},
{
"name": "=returnOnAdSpend",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"name": "=sessionSource",
"listName": "other"
},
{
"name": "=sessionMedium",
"listName": "other"
},
{
"name": "=sessionCampaignName",
"listName": "other"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "032022fe-a6c8-4b9f-81ec-8c4bc3732a4b",
"name": "BQ - ga4_ads_data",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
1312
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily table for advertising performance metrics.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_ads_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n sessionSource STRING,\n sessionMedium STRING,\n sessionCampaignName STRING,\n ecommercePurchases INT64,\n averagePurchaseRevenue FLOAT64,\n purchaseRevenue FLOAT64,\n advertiserAdClicks INT64,\n advertiserAdCost FLOAT64,\n advertiserAdCostPerClick FLOAT64,\n returnOnAdSpend FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_ads_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, sessionSource, sessionMedium, sessionCampaignName, ecommercePurchases, averagePurchaseRevenue, purchaseRevenue, advertiserAdClicks, advertiserAdCost, advertiserAdCostPerClick, returnOnAdSpend)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', '${row.dimensionValues[2].value}', '${row.dimensionValues[3].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'}, ${row.metricValues[4].value || 'NULL'}, ${row.metricValues[5].value || 'NULL'}, ${row.metricValues[6].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "b7acb21d-1d3a-44aa-a6a6-d61e877f6d0c",
"name": "GA4 - All Metrics",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
1504
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{
"listName": "sessions"
},
{},
{
"listName": "userEngagementDuration"
},
{
"name": "=newUsers",
"listName": "other"
},
{
"name": "=engagementRate",
"listName": "other"
},
{
"name": "=engagedSessions",
"listName": "other"
},
{
"listName": "screenPageViews"
},
{
"name": "=purchaseRevenue",
"listName": "other"
},
{
"name": "=ecommercePurchases",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "3c5039ee-07b4-4dab-af2a-4cedaa5e773d",
"name": "BQ - ga4_all_metrics_data",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
1504
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily summary table of all key metrics.\n-- This version is corrected to match the exact output of the GA4 - All Metrics node.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_all_metrics_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n sessions INT64,\n totalUsers INT64,\n userEngagementDuration FLOAT64,\n newUsers INT64,\n engagementRate FLOAT64,\n engagedSessions INT64,\n screenPageViews INT64,\n purchaseRevenue FLOAT64,\n ecommercePurchases INT64\n);\n\n-- Insert data from the GA4 node with the correct metric mapping.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_all_metrics_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, sessions, totalUsers, userEngagementDuration, newUsers, engagementRate, engagedSessions, screenPageViews, purchaseRevenue, ecommercePurchases)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'}, ${row.metricValues[4].value || 'NULL'}, ${row.metricValues[5].value || 'NULL'}, ${row.metricValues[6].value || 'NULL'}, ${row.metricValues[7].value || 'NULL'}, ${row.metricValues[8].value || 'NULL'})`).join(',') }};",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "3f5878e3-0809-4744-9c8a-d616c63dff45",
"name": "GA4 - Event Metrics",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
1696
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{
"name": "custom_metric",
"listName": "=eventCount"
},
{
"name": "=eventValue",
"listName": "other"
},
{
"name": "=eventCountPerUser",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"name": "=eventName",
"listName": "other"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "fc58d30d-3350-4466-8fe2-330510ebb890",
"name": "BQ - ga4_event_metrics_data",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
1696
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily table for event-specific metrics.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_event_metrics_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n eventName STRING,\n eventCount INT64,\n eventCountPerUser FLOAT64,\n eventValue FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_event_metrics_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, eventName, eventCount, eventCountPerUser, eventValue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "48bfa988-0088-4ce2-a7da-14496dda8738",
"name": "GA4 - Page Location",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
1888
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{},
{
"name": "=ecommercePurchases",
"listName": "other"
},
{
"listName": "screenPageViews"
},
{
"name": "=purchaseRevenue",
"listName": "other"
},
{
"listName": "eventCount"
},
{
"name": "=engagementRate",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"listName": "pageLocation"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "2533064a-f1c2-4bab-9f72-8368fe5de632",
"name": "BQ - ga4_page_location_data",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
1888
],
"parameters": {
"options": {},
"sqlQuery": "-- Creates and populates a daily table for metrics by page location.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_page_location_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n pageLocation STRING,\n totalUsers INT64,\n ecommercePurchases INT64,\n purchaseRevenue FLOAT64,\n screenPageViews INT64,\n eventCount INT64,\n engagementRate FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_page_location_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, pageLocation, totalUsers, ecommercePurchases, purchaseRevenue, screenPageViews, eventCount, engagementRate)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'}, ${row.metricValues[4].value || 'NULL'}, ${row.metricValues[5].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "280f8dbe-dea6-41b5-a96c-9b49ee2c3248",
"name": "GA4 - Landing Page",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
2080
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{},
{
"listName": "sessions"
},
{
"listName": "eventCount"
},
{
"name": "=ecommercePurchases",
"listName": "other"
},
{
"name": "=engagementRate",
"listName": "other"
},
{
"name": "=purchaseRevenue",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"name": "=landingPage",
"listName": "=other"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "89e42bf3-90fe-40e4-a3aa-a588a7a6eb2f",
"name": "GA4 - Transaction Items",
"type": "n8n-nodes-base.googleAnalytics",
"position": [
208,
-224
],
"parameters": {
"simple": false,
"endDate": "={{ $json.endDate }}",
"dateRange": "custom",
"returnAll": true,
"startDate": "={{ $json.startDate }}",
"metricsGA4": {
"metricValues": [
{
"name": "=itemPurchaseQuantity",
"listName": "other"
},
{
"name": "=itemRevenue",
"listName": "other"
}
]
},
"propertyId": {
"__rl": true,
"mode": "id",
"value": "={{ $json['GA4 Property ID'] }}"
},
"dimensionsGA4": {
"dimensionValues": [
{},
{
"name": "=transactionId",
"listName": "other"
},
{
"listName": "itemName"
}
]
},
"additionalFields": {}
},
"credentials": {
"googleAnalyticsOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "6f95331c-4b34-4427-ab2d-38da7716a453",
"name": "BQ - ga4_transaction_items",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
-224
],
"parameters": {
"options": {},
"sqlQuery": "-- This query first creates a new table for the specified date range, replacing it if it already exists.\n-- Then, it inserts the transaction data passed from the previous n8n node.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_transaction_items_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n transactionId STRING,\n itemName STRING,\n itemPurchaseQuantity INT64,\n itemRevenue FLOAT64\n);\n\n-- Insert data from the GA4 node into the newly created table.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_transaction_items_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, transactionId, itemName, itemPurchaseQuantity, itemRevenue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[2].value}'), '${row.dimensionValues[0].value}', '${row.dimensionValues[1].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1,
"alwaysOutputData": false
},
{
"id": "5dc8ff31-180d-4762-a420-39bb91b0a286",
"name": "Backfill Config",
"type": "n8n-nodes-base.set",
"position": [
-16,
928
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "e3e88ddb-e0de-4400-8de4-220fa8651d21",
"name": "=GA4 Property ID",
"type": "string",
"value": "461978355"
},
{
"id": "4c4ca0dd-c7dd-466c-8a8e-028da8377d49",
"name": "project_id",
"type": "string",
"value": "sublime-flux-378608"
},
{
"id": "f0b12ee2-88f1-4d47-af66-f9250dafab57",
"name": "dataset_id",
"type": "string",
"value": "GA4"
},
{
"id": "8a6d84bb-a106-403b-a34e-8e33a3a2910a",
"name": "startDate",
"type": "string",
"value": "={{ DateTime.now().minus({ days: 2 }).toFormat('yyyy-MM-dd') }}"
},
{
"id": "c3d4c4ea-f94a-4e40-8d85-f47e80942bf8",
"name": "endDate",
"type": "string",
"value": "={{ DateTime.now().minus({ days: 2 }).toFormat('yyyy-MM-dd') }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "6f6e0a0a-f81a-4573-b0ce-bf96db048777",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-240,
928
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtMinute": 27
}
]
}
},
"typeVersion": 1.2
},
{
"id": "b18f7c11-b540-46cd-83f4-f962f47cf345",
"name": "BQ - ga4_landing_page_data",
"type": "n8n-nodes-base.googleBigQuery",
"onError": "continueRegularOutput",
"position": [
432,
2080
],
"parameters": {
"options": {
"timeoutMs": 500000
},
"sqlQuery": "-- Creates and populates a daily table for landing page performance metrics.\nCREATE OR REPLACE TABLE `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_landing_page_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (\n date DATE,\n landingPage STRING,\n totalUsers INT64,\n sessions INT64,\n eventCount INT64,\n ecommercePurchases INT64,\n engagementRate FLOAT64,\n purchaseRevenue FLOAT64\n);\n\n-- Insert data from the GA4 node.\nINSERT INTO `{{ $('Backfill Config').item.json.project_id }}`.`{{ $('Backfill Config').item.json.dataset_id }}`.ga4_landing_page_data_{{ $('Backfill Config').item.json.startDate.replaceAll('-', '') }} (date, landingPage, totalUsers, sessions, eventCount, ecommercePurchases, engagementRate, purchaseRevenue)\nVALUES\n{{ $items()[0].json.rows.map(row => `(PARSE_DATE('%Y%m%d', '${row.dimensionValues[0].value}'), '${row.dimensionValues[1].value}', ${row.metricValues[0].value || 'NULL'}, ${row.metricValues[1].value || 'NULL'}, ${row.metricValues[2].value || 'NULL'}, ${row.metricValues[3].value || 'NULL'}, ${row.metricValues[4].value || 'NULL'}, ${row.metricValues[5].value || 'NULL'})`).join(',') }};\n",
"projectId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Backfill Config').item.json.project_id }}"
}
},
"credentials": {
"googleBigQueryOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "121381a5-247a-47d9-a65f-3fc526c2011b",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
1664,
640
],
"parameters": {
"numberInputs": 10
},
"typeVersion": 3.2
},
{
"id": "67d2d83b-47cd-4adb-9794-56792090e1f7",
"name": "Merge1",
"type": "n8n-nodes-base.merge",
"position": [
2144,
976
],
"parameters": {
"numberInputs": 4
},
"typeVersion": 3.2
},
{
"id": "1d9603e7-41af-4dc5-814b-bd361409d4b9",
"name": "Code",
"type": "n8n-nodes-base.code",
"position": [
2352,
976
],
"parameters": {
"jsCode": "// This code processes the results from all BigQuery nodes and creates a summary message.\n\n// Statically define the names of the BigQuery nodes in the exact order they are connected to the Merge node(s).\nconst nodeNames = [\n 'BQ - ga4_transaction_items',\n 'BQ - ga4_data_session_channel_group',\n 'BQ - ga4_data_session_source_campaign_medium',\n 'BQ - ga4_data_country_language_city',\n 'BQ - ga4_data_item_name',\n 'BQ - ga4_data_browser_os_device',\n 'BQ - ga4_data_first_user_source_medium',\n 'BQ - ga4_data_first_user_channel_group',\n 'BQ - ga4_ads_data',\n 'BQ - ga4_all_metrics_data',\n 'BQ - ga4_event_metrics_data',\n 'BQ - ga4_page_location_data',\n 'BQ - ga4_landing_page_data'\n];\n\nconst successfulNodes = [];\nconst failedNodes = [];\n\n// Loop through all the input items from the previous nodes.\nfor (const [index, item] of $input.all().entries()) {\n const nodeName = nodeNames[index] || `Unknown Node (Input ${index + 1})`;\n\n if (item.json.error) {\n // Escape underscores in the node name to prevent Markdown parsing errors\n const escapedNodeName = nodeName.replace(/_/g, '\\\\_');\n failedNodes.push(escapedNodeName);\n } else {\n successfulNodes.push(nodeName);\n }\n}\n\n// Start building the message string with the success count.\nlet message = `GA4 to BigQuery Workflow Status: ${successfulNodes.length}/13 Successful \u2705\\n\\n`;\n\n// Add a section for failed nodes only if there are any.\nif (failedNodes.length > 0) {\n message += \"\u274c **Failed Nodes:**\\n\" + failedNodes.join(\"\\n\");\n}\n\n// Return the final message to be used in the Telegram node.\nreturn [{ json: { message: message } }];"
},
"typeVersion": 2
},
{
"id": "960ed711-34ff-4edd-ba94-146ba81ab8cd",
"name": "Send a text message",
"type": "n8n-nodes-base.telegram",
"position": [
2560,
976
],
"parameters": {
"text": "={{ $json.message }}",
"chatId": "123456789",
"additionalFields": {
"appendAttribution": false
}
},
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "53436acd-dc75-460a-a7ca-dd09ab527891",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1040,
-304
],
"parameters": {
"color": 7,
"width": 992,
"height": 1056,
"content": "# \ud83d\ude80 N8N GA4 Backfill Workflow\n\n## Automate your GA4 Backfilling!\n\nThis workflow fetches key reports from Google Analytics 4 and loads them into Google BigQuery, complete with status alerts.\n\n### \ud83d\udccb How to Use\n\n**1. Configure Workflow \u2699\ufe0f**\n- Open the **Backfill Config** node.\n- Set your `project_id`, `dataset_id`, date range, and `GA4 Property ID`.\n\n**2. Set Credentials \ud83d\udd11**\n- Authenticate your Google Analytics and Google BigQuery accounts in one of each type of node.\n- Set up your Telegram credentials and Chat ID in the final **Telegram** node.\n\n**3. Run the Workflow \u25b6\ufe0f**\n- Activate the workflow to run on its schedule via the **Schedule Trigger**, or run it manually at any time.\n\n---\n\n*For detailed instructions, questions, or more information, please visit the [GitHub repository](https://github.com/aliasoblomov/N8N-GA4-Backfill-Workflow).*"
},
"typeVersion": 1
},
{
"id": "33fc9b3a-298b-4471-9859-5cf9a592c3d7",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1040,
-304
],
"parameters": {
"color": 5,
"width": 3888,
"height": 2624,
"content": ""
},
"typeVersion": 1
}
],
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "ee3fd9f6-3dc8-4128-a2b7-5f09414c4e68",
"connections": {
"Code": {
"main": [
[
{
"node": "Send a text message",
"type": "main",
"index": 0
}
]
]
},
"Merge": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 0
}
]
]
},
"Merge1": {
"main": [
[
{
"node": "Code",
"type": "main",
"index": 0
}
]
]
},
"GA4 - Ads Data": {
"main": [
[
{
"node": "BQ - ga4_ads_data",
"type": "main",
"index": 0
}
]
]
},
"Backfill Config": {
"main": [
[
{
"node": "GA4 - Transaction Items",
"type": "main",
"index": 0
},
{
"node": "GA4 - Session Channel Group",
"type": "main",
"index": 0
},
{
"node": "GA4 - Session Source/Campaign/Medium",
"type": "main",
"index": 0
},
{
"node": "GA4 - Country/Language/City",
"type": "main",
"index": 0
},
{
"node": "GA4 - Item Name",
"type": "main",
"index": 0
},
{
"node": "GA4 - Browser/OS/Device",
"type": "main",
"index": 0
},
{
"node": "GA4 - First User Source/Medium",
"type": "main",
"index": 0
},
{
"node": "GA4 - First User Channel Group",
"type": "main",
"index": 0
},
{
"node": "GA4 - Ads Data",
"type": "main",
"index": 0
},
{
"node": "GA4 - All Metrics",
"type": "main",
"index": 0
},
{
"node": "GA4 - Event Metrics",
"type": "main",
"index": 0
},
{
"node": "GA4 - Page Location",
"type": "main",
"index": 0
},
{
"node": "GA4 - Landing Page",
"type": "main",
"index": 0
}
]
]
},
"GA4 - Item Name": {
"main": [
[
{
"node": "BQ - ga4_data_item_name",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Backfill Config",
"type": "main",
"index": 0
}
]
]
},
"BQ - ga4_ads_data": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 8
}
]
]
},
"GA4 - All Metrics": {
"main": [
[
{
"node": "BQ - ga4_all_metrics_data",
"type": "main",
"index": 0
}
]
]
},
"GA4 - Landing Page": {
"main": [
[
{
"node": "BQ - ga4_landing_page_data",
"type": "main",
"index": 0
}
]
]
},
"GA4 - Event Metrics": {
"main": [
[
{
"node": "BQ - ga4_event_metrics_data",
"type": "main",
"index": 0
}
]
]
},
"GA4 - Page Location": {
"main": [
[
{
"node": "BQ - ga4_page_location_data",
"type": "main",
"index": 0
}
]
]
},
"BQ - ga4_data_item_name": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 4
}
]
]
},
"GA4 - Browser/OS/Device": {
"main": [
[
{
"node": "BQ - ga4_data_browser_os_device",
"type": "main",
"index": 0
}
]
]
},
"GA4 - Transaction Items": {
"main": [
[
{
"node": "BQ - ga4_transaction_items",
"type": "main",
"index": 0
}
]
]
},
"BQ - ga4_all_metrics_data": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 9
}
]
]
},
"BQ - ga4_landing_page_data": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 3
}
]
]
},
"BQ - ga4_transaction_items": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"BQ - ga4_event_metrics_data": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 1
}
]
]
},
"BQ - ga4_page_location_data": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 2
}
]
]
},
"GA4 - Country/Language/City": {
"main": [
[
{
"node": "BQ - ga4_data_country_language_city",
"type": "main",
"index": 0
}
]
]
},
"GA4 - Session Channel Group": {
"main": [
[
{
"node": "BQ - ga4_data_session_channel_group",
"type": "main",
"index": 0
}
]
]
},
"GA4 - First User Channel Group": {
"main": [
[
{
"node": "BQ - ga4_data_first_user_channel_group",
"type": "main",
"index": 0
}
]
]
},
"GA4 - First User Source/Medium": {
"main": [
[
{
"node": "BQ - ga4_data_first_user_source_medium",
"type": "main",
"index": 0
}
]
]
},
"BQ - ga4_data_browser_os_device": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 5
}
]
]
},
"BQ - ga4_data_country_language_city": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 3
}
]
]
},
"BQ - ga4_data_session_channel_group": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"GA4 - Session Source/Campaign/Medium": {
"main": [
[
{
"node": "BQ - ga4_data_session_source_campaign_medium",
"type": "main",
"index": 0
}
]
]
},
"BQ - ga4_data_first_user_channel_group": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 7
}
]
]
},
"BQ - ga4_data_first_user_source_medium": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 6
}
]
]
},
"BQ - ga4_data_session_source_campaign_medium": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 2
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleAnalyticsOAuth2googleBigQueryOAuth2ApitelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automates the daily backfill of Google Analytics 4 (GA4) data into BigQuery. It fetches 13 essential pre-processed reports (including User Acquisition, Traffic, and E-commerce) and uploads them to automatically created tables in BigQuery, and then send an alert in…
Source: https://n8n.io/workflows/11010/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
This workflow runs on scheduled weekly and monthly triggers to generate unified marketing performance reports. It processes multiple websites by collecting analytics data, paid ads performance, and CR
Fetch Multiple Google Analytics GA4 metrics daily, post to Discord, update previous day’s entry as GA data finalizes over seven days. Automates daily traffic reporting Maintains single message per day
This automation creates a seamless daily pipeline that: Pulls yesterday's website visitors from Leadfeeder Enriches company data using Apollo.io's powerful database Delivers enriched leads to your Goo
Google analytics template. Uses scheduleTrigger, manualTrigger, stickyNote, googleAnalytics. Scheduled trigger; 22 nodes.
If you own a website and need to analyze your Google analytics data If you need to create an SEO report on which pages are getting most traffic or how your google search terms are performing If you wa