Sync Shopify Order UTM Data to Baserow
Automate tracking Shopify order UTM parameters in Baserow. This workflow fetches daily orders via GraphQL, extracts marketing campaign data, and syncs it to your Baserow database for easy analysis.
Overview
Automatically syncs Shopify order and UTM marketing data to a Baserow database for campaign performance tracking.
🧠 Description & Use Case
This workflow automatically tracks the performance of your marketing campaigns by syncing order data and their associated UTM parameters from Shopify to a Baserow database. By capturing the first-touch attribution data (like utm_source, utm_medium, and utm_campaign), you can directly measure the revenue generated by specific marketing efforts.
🔄 How It Works:
-
Scheduled Trigger
- The workflow runs automatically every day at midnight, ensuring you get a daily summary of the previous day's campaign performance.
-
Fetch Shopify Orders via GraphQL
- It uses a custom GraphQL query to fetch all orders created in the last 24 hours from your Shopify store.
- Crucially, the query requests the
customerJourneySummary, which contains the vitalutmParametersfrom the customer's first visit.
-
Process Orders Individually
- The
Split Shopify datanode takes the batch of orders and processes each one as a separate item, allowing for individual analysis.
- The
-
Transform and Clean Data
- A
Setnode restructures the complex data from Shopify into a simple, flat format. It extracts key fields like order name, revenue, and all UTM parameters (campaign,content,medium,source,term).
- A
-
Filter for Campaign-Driven Orders
- An
IFnode checks if acampaignUTM parameter exists for the order. This ensures that only orders originating from a tracked marketing campaign are logged.
- An
-
Log Data to Baserow
- If an order has a campaign tag, a new row is created in your designated Baserow table, populating it with the order details and its corresponding UTM data.
✅ Real-World Use Cases:
- Marketing ROI Analysis: Directly connect marketing campaigns to the revenue they generate, allowing you to calculate your return on investment accurately.
- Campaign Performance Dashboard: Use the structured data in Baserow to build dashboards that visualize which campaigns, sources, and ad creatives are most effective.
- Automated Reporting: Eliminate the tedious manual process of exporting Shopify reports and cleaning data in spreadsheets. This workflow provides a clean, ready-to-use dataset every day.
- Customer Acquisition Insights: Understand which channels (e.g., Google Ads, Facebook, email newsletters) are bringing in the most valuable customers by analyzing
utm_sourceandutm_medium.
Instructions
Basic steps
- Download workflow JSON
- Import into n8n
- Configure node parameters as needed
- Test and enable the workflow
💡 Tips
After importing, verify all connectors and credentials match your environment.
Preview
Workflow Visualization
Nodes
Baserow
baserow
No Operation, do nothing
noOp
Set Shopify Subdomain
set
Get orders from Shopify
graphql
Every day at 00:00
scheduleTrigger
Split Shopify data into n8n items
splitOut
Transform incoming data structure
set
Check if "Campaign" is present
if
Sticky Note4
stickyNote
Sticky Note3
stickyNote
Sticky Note
stickyNote
Sticky Note2
stickyNote
Statistics
View full JSON structure
{
"nodes": [
{
"id": "2ba892fc-59c9-442b-aa21-a5c23b6076e5",
"name": "Baserow",
"type": "n8n-nodes-base.baserow",
"position": [
2860,
380
],
"parameters": {
"tableId": 646,
"fieldsUi": {
"fieldValues": [
{
"fieldId": 6164,
"fieldValue": "={{ $json.order }}"
},
{
"fieldId": 6165,
"fieldValue": "={{ $json.campaign }}"
},
{
"fieldId": 6166,
"fieldValue": "={{ $json.content }}"
},
{
"fieldId": 6167,
"fieldValue": "={{ $json.medium }}"
},
{
"fieldId": 6168,
"fieldValue": "={{ $json.source }}"
},
{
"fieldId": 6170,
"fieldValue": "={{ $json.revenue }}"
}
]
},
"operation": "create",
"databaseId": 121
},
"credentials": {
"baserowApi": {
"id": "VaQgKQ8NPXVMrvMl",
"name": "Baserow account"
}
},
"typeVersion": 1
},
{
"id": "e35a0417-7a6a-46bb-8970-20aa7c19d168",
"name": "No Operation, do nothing",
"type": "n8n-nodes-base.noOp",
"position": [
2860,
720
],
"parameters": {},
"typeVersion": 1
},
{
"id": "76e327e9-2cc2-42dd-b31a-1aa1e9b02cd1",
"name": "Set Shopify Subdomain",
"type": "n8n-nodes-base.set",
"position": [
1900,
320
],
"parameters": {
"fields": {
"values": [
{
"name": "Shopify Subdomain",
"stringValue": "you-domain"
}
]
},
"options": {}
},
"typeVersion": 3.2
},
{
"id": "85c0f561-a75d-44a4-a8a5-3791c10a2891",
"name": "Get orders from Shopify",
"type": "n8n-nodes-base.graphql",
"position": [
1900,
560
],
"parameters": {
"query": "=query yersterdaysOrders {\n orders(query: \"created_at:{{$today.minus({days: 1})}}\", first: 100) {\n edges {\n node {\n id\n name\n totalReceived\n customerJourneySummary {\n firstVisit {\n id\n source\n referrerUrl\n landingPage\n utmParameters {\n campaign\n content\n medium\n source\n term\n }\n }\n }\n }\n }\n }\n}",
"endpoint": "=https://{{ $('Set Shopify Subdomain').params[\"fields\"][\"values\"][0][\"stringValue\"] }}.myshopify.com/admin/api/2024-01/graphql.json",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "dPZdfPnUTz1YJ54o",
"name": "Shopify Header Auth - lanakk.com"
}
},
"typeVersion": 1
},
{
"id": "4ddbe343-6d4f-4079-9c60-bdf2c34fb015",
"name": "Every day at 00:00",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
1660,
560
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.1
},
{
"id": "6b3dd6f7-a761-4a01-bb77-cb8689fe64a0",
"name": "Split Shopify data into n8n items",
"type": "n8n-nodes-base.splitOut",
"position": [
2120,
560
],
"parameters": {
"options": {},
"fieldToSplitOut": "data.orders.edges"
},
"typeVersion": 1
},
{
"id": "c50ca221-1330-44c9-9877-3b5bd36a05fb",
"name": "Transform incoming data structure",
"type": "n8n-nodes-base.set",
"position": [
2340,
560
],
"parameters": {
"fields": {
"values": [
{
"name": "order",
"stringValue": "={{ $json.node.name }}"
},
{
"name": "campaign",
"stringValue": "={{ $json.node.customerJourneySummary.firstVisit.utmParameters.campaign }}"
},
{
"name": "content",
"stringValue": "={{ $json.node.customerJourneySummary.firstVisit.utmParameters.content || \"\" }}"
},
{
"name": "medium",
"stringValue": "={{ $json.node.customerJourneySummary.firstVisit.utmParameters.medium || \"\" }}"
},
{
"name": "source",
"stringValue": "={{ $json.node.customerJourneySummary.firstVisit.utmParameters.medium || \"\" }}"
},
{
"name": "term",
"stringValue": "={{ $json.node.customerJourneySummary.firstVisit.utmParameters.term || \"\" }}"
},
{
"name": "revenue",
"type": "numberValue",
"numberValue": "={{ $json.node.totalReceived }}"
}
]
},
"include": "none",
"options": {}
},
"typeVersion": 3.2
},
{
"id": "c84c3619-fd41-4d06-8894-1ba7998477fb",
"name": "Check if \"Campaign\" is present",
"type": "n8n-nodes-base.if",
"position": [
2560,
560
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "61fe8905-1b9f-45d9-9742-2d5799200d18",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.campaign }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "b0f07670-4fdd-4b64-8d77-87ea5cc399ac",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1240,
460
],
"parameters": {
"color": 4,
"width": 360.408084305475,
"height": 315.5897364788551,
"content": "## Shopify API\n\nThis workflow uses GraphQL calls to the Shopify Admin API. In order to get a better understanding for the queries and mutations please check the API Docs.\n\n\n[Shopify GraphQL API docs](https://shopify.dev/docs/api/admin-graphql)\n\nTo make it easy to build queries for the GraphQL API easy please check out the [GraphiQL App for the Admin API](https://shopify.dev/docs/apps/tools/graphiql-admin-api) from Shopify"
},
"typeVersion": 1
},
{
"id": "742d92d7-9c3e-4515-a9ca-d840685d8ebf",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1720,
120
],
"parameters": {
"width": 279.1188177339898,
"content": "## Set your Shopify Subdomain here"
},
"typeVersion": 1
},
{
"id": "a4feb388-0d60-41ee-a269-d39717c6267c",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1900,
760
],
"parameters": {
"width": 279.1188177339898,
"content": "## Shopify \nThe n8n Shopify node cannot get the customer journey, so we get this from the Shopify GraphQL API"
},
"typeVersion": 1
},
{
"id": "adc71ed1-fcb9-40fa-b3c8-ccca7e2fc699",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
3060,
360
],
"parameters": {
"width": 279.1188177339898,
"height": 157.7820535313736,
"content": "## Baserow\nPlease map the fields coming from the IF node to your own structure in Baserow"
},
"typeVersion": 1
}
],
"connections": {
"Every day at 00:00": {
"main": [
[
{
"node": "Set Shopify Subdomain",
"type": "main",
"index": 0
},
{
"node": "Get orders from Shopify",
"type": "main",
"index": 0
}
]
]
},
"Get orders from Shopify": {
"main": [
[
{
"node": "Split Shopify data into n8n items",
"type": "main",
"index": 0
}
]
]
},
"Check if \"Campaign\" is present": {
"main": [
[
{
"node": "Baserow",
"type": "main",
"index": 0
}
],
[
{
"node": "No Operation, do nothing",
"type": "main",
"index": 0
}
]
]
},
"Split Shopify data into n8n items": {
"main": [
[
{
"node": "Transform incoming data structure",
"type": "main",
"index": 0
}
]
]
},
"Transform incoming data structure": {
"main": [
[
{
"node": "Check if \"Campaign\" is present",
"type": "main",
"index": 0
}
]
]
}
}
}Actions
Technical Specs
Compatibility
License
This workflow template follows MIT license, you can freely use, modify and distribute.
Please comply with relevant third-party service terms when using.