This workflow follows the Google Sheets → HTTP Request recipe pattern — see all workflows that pair these two integrations.
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 →
{
"nodes": [
{
"id": "8a4ba8b8-b76e-4572-becd-e7f8fbea2651",
"name": "EXTRACT CAMPAIGN DATA",
"type": "n8n-nodes-base.httpRequest",
"position": [
500,
960
],
"parameters": {
"url": "=https://server.smartlead.ai/api/v1/campaigns/{{ $json.id }}/leads-export",
"options": {
"batching": {
"batch": {
"batchSize": 0
}
}
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "api_key",
"value": "={{ $json['API KEY'] }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "90011ed6-180d-4170-8932-ac3aa7d0e5df",
"name": "FETCH ALL CAMPAIGNS",
"type": "n8n-nodes-base.httpRequest",
"position": [
-20,
940
],
"parameters": {
"url": "https://server.smartlead.ai/api/v1/campaigns",
"options": {
"batching": {
"batch": {
"batchSize": 0
}
}
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "api_key",
"value": "={{ $json['API KEY'] }}"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "c41afcf1-9256-47fa-ad99-3e1af880e53d",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
200,
940
],
"parameters": {
"options": {
"reset": "={{ $node['Loop Over Items'].context[\"done\"] }}"
}
},
"typeVersion": 3
},
{
"id": "606bfc18-1d70-4d64-ac70-ae6f42bf0dbb",
"name": "UPDATE CAMPAIGN",
"type": "n8n-nodes-base.postgres",
"position": [
720,
1220
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "ce_campaign",
"cachedResultName": "ce_campaign"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "outbound_activities",
"cachedResultName": "outbound_activities"
},
"columns": {
"value": {
"name": "={{ $json.name }}",
"status": "={{ $json.status }}",
"user_id": "={{ $json.user_id }}",
"client_id": "={{ $json.client_id }}",
"created_at": "={{ $json.created_at }}",
"updated_at": "={{ $json.updated_at }}",
"campaign_id": "={{ $json.id }}",
"track_settings": "={{ $json.track_settings }}",
"unsubscribe_text": "={{ $json.unsubscribe_text }}",
"max_leads_per_day": "={{ $json.max_leads_per_day }}",
"parent_campaign_id": "={{ $json.parent_campaign_id }}",
"send_as_plain_text": "={{ $json.send_as_plain_text }}",
"stop_lead_settings": "={{ $json.stop_lead_settings }}",
"follow_up_percentage": "={{ $json.follow_up_percentage }}",
"min_time_btwn_emails": "={{ $json.min_time_btwn_emails }}",
"scheduler_cron_value": "={{ $json.scheduler_cron_value }}",
"enable_ai_esp_matching": "={{ $json.enable_ai_esp_matching }}",
"psg_last_update_timestamp": "={{ $now }}"
},
"schema": [
{
"id": "campaign_id",
"type": "number",
"display": true,
"removed": false,
"required": true,
"displayName": "campaign_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "user_id",
"type": "number",
"display": true,
"required": false,
"displayName": "user_id",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "created_at",
"type": "dateTime",
"display": true,
"required": true,
"displayName": "created_at",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "updated_at",
"type": "dateTime",
"display": true,
"required": true,
"displayName": "updated_at",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "status",
"type": "string",
"display": true,
"required": true,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "name",
"type": "string",
"display": true,
"required": false,
"displayName": "name",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "track_settings",
"type": "array",
"display": true,
"required": false,
"displayName": "track_settings",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "scheduler_cron_value",
"type": "object",
"display": true,
"required": false,
"displayName": "scheduler_cron_value",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "min_time_btwn_emails",
"type": "number",
"display": true,
"required": false,
"displayName": "min_time_btwn_emails",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "max_leads_per_day",
"type": "number",
"display": true,
"required": false,
"displayName": "max_leads_per_day",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "stop_lead_settings",
"type": "string",
"display": true,
"required": false,
"displayName": "stop_lead_settings",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "enable_ai_esp_matching",
"type": "boolean",
"display": true,
"required": false,
"displayName": "enable_ai_esp_matching",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "send_as_plain_text",
"type": "boolean",
"display": true,
"required": false,
"displayName": "send_as_plain_text",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "follow_up_percentage",
"type": "number",
"display": true,
"required": false,
"displayName": "follow_up_percentage",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "unsubscribe_text",
"type": "string",
"display": true,
"required": false,
"displayName": "unsubscribe_text",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "parent_campaign_id",
"type": "number",
"display": true,
"required": false,
"displayName": "parent_campaign_id",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "client_id",
"type": "number",
"display": true,
"required": false,
"displayName": "client_id",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "psg_last_update_timestamp",
"type": "dateTime",
"display": true,
"required": false,
"displayName": "psg_last_update_timestamp",
"defaultMatch": false,
"canBeUsedToMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"campaign_id"
]
},
"options": {
"queryBatching": "independently"
},
"operation": "upsert"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.5
},
{
"id": "b9f61fd6-9327-428e-9e78-4ca0779476ea",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
1220,
980
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3
},
{
"id": "b8c1082d-a12f-4e56-af8c-73641b45da67",
"name": "Code",
"type": "n8n-nodes-base.code",
"notes": "// Retrieve the CSV-like data from the 'data' field in the input\nconst csvData = $json['data']; // Ensure that 'data' is the correct field name\n\n// Check if csvData exists and is not empty\nif (!csvData) {\n console.log(\"Input data structure:\", $json); // Debugging output to inspect input structure\n throw new Error('No CSV data provided. Ensure the correct field reference is being used.');\n}\n\n// Split the CSV into rows\nconst rows = csvData.split('\\n');\n\n// Extract the headers\nconst headers = rows[0].replace(/\"/g, '').split(',');\n\n// Iterate over each data row and map it to an object\nconst output = rows.slice(1).map(row => {\n const values = row.match(/(\".*?\"|[^\",]+)(?=\\s*,|\\s*$)/g).map(value => {\n // Remove surrounding quotes from each value if present\n return value.startsWith('\"') && value.endsWith('\"') ? value.slice(1, -1) : value;\n });\n\n const item = {};\n headers.forEach((header, index) => {\n item[header] = values[index] || null;\n });\n\n return { json: item };\n});\n\nreturn output;",
"position": [
720,
960
],
"parameters": {
"jsCode": "// Retrieve the CSV-like data from the 'data' field in the input\nconst csvData = items[0].json.data; // Ensure that 'data' is the correct field name\n\n// Check if csvData exists and is not empty\nif (!csvData) {\n console.log(\"Input data structure:\", ); // Debugging output to inspect input structure\n throw new Error('No CSV data provided. Ensure the correct field reference is being used.');\n}\n\nif (typeof csvData !== 'string') {\n throw new Error('CSV data is not a string. Please check the input data format.');\n}\n\n// Preprocess the CSV data to handle missing values\nconst preprocessedCsvData = csvData.replace(/,,/g, ',\"\",');\n\n// Split the CSV into rows\nconst rows = preprocessedCsvData.split(/\\r?\\n/); // Adjust to handle different line endings\n\n// Define the expected number of columns based on CSV structure\nconst expectedNumberOfColumns = 22;\n\n// Iterate over each data row starting from the second row (index 1) and map it to an object\nconst output = rows.slice(1).map((row, index) => {\n // Split the row into values, accounting for empty columns using regex\n const values = row.split(/,(?=(?:(?:[^\"]*\"){2})*[^\"]*$)/).map(value => {\n // Remove surrounding quotes from each value if present and trim whitespace\n return value.startsWith('\"') && value.endsWith('\"') ? value.slice(1, -1).trim() : value.trim();\n });\n\n // Ensure that the number of values matches the expected number of columns\n while (values.length < expectedNumberOfColumns) {\n values.push(\"\"); // Add empty strings for missing values\n }\n\n // Check if the number of values matches expected columns\n if (values.length !== expectedNumberOfColumns) {\n console.warn(`Row ${index + 1} doesn't have the expected number of columns. Skipping this entry.`);\n return null; // Skip this row if it doesn't match the expected columns\n }\n\n // Create an item object with a fixed structure\n const item = {\n id: values[0] || null,\n campaign_lead_map_id: values[1] || null,\n status: values[2] || null,\n category: values[3] || null,\n is_interested: values[4] === 'true', // Convert to boolean\n created_at: values[5] || null,\n first_name: values[6] || null,\n last_name: values[7] || null,\n email: values[8] || null,\n phone_number: values[9] || null,\n company_name: values[10] || null,\n website: values[11] || null,\n location: values[12] || null,\n custom_fields: values[13] || null,\n linkedin_profile: values[14] || null,\n company_url: values[15] || null,\n is_unsubscribed: values[16] === 'true', // Convert to boolean\n unsubscribed_client_id_map: values[17] || null,\n last_email_sequence_sent: values[18] || null,\n open_count: parseInt(values[19], 10) || 0, // Convert to number\n click_count: parseInt(values[20], 10) || 0, // Convert to number\n reply_count: parseInt(values[21], 10) || 0 // Convert to number\n };\n\n return { json: item };\n}).filter(item => item !== null); // Remove null entries from output\n\n// Return the structured output\nreturn output;\n"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "f6550deb-0479-475e-b3ba-9507a4ac8911",
"name": "Loop Over Items1",
"type": "n8n-nodes-base.splitInBatches",
"position": [
180,
160
],
"parameters": {
"options": {
"reset": "={{ $node['Loop Over Items1'].context[\"done\"] }}"
}
},
"typeVersion": 3
},
{
"id": "a183df85-17a2-4886-adc9-68b5ab5fa8b0",
"name": "HubSpot",
"type": "n8n-nodes-base.hubspot",
"position": [
420,
180
],
"parameters": {
"operation": "getAll",
"authentication": "oAuth2",
"additionalFields": {}
},
"credentials": {
"hubspotOAuth2Api": {
"name": "<your credential>"
}
},
"executeOnce": false,
"typeVersion": 2.1,
"alwaysOutputData": true
},
{
"id": "da7e2980-6f82-4867-a460-306095234f5f",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
640,
180
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "e77d0ee2-bb31-483b-98ee-b0acb0b54bb4",
"operator": {
"type": "boolean",
"operation": "false",
"singleValue": true
},
"leftValue": "={{ $json.companyId.isEmpty() }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "9247f4c5-05dd-48a4-8bf9-c67a8936570c",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1340,
980
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.2
},
{
"id": "16623c02-5fb6-40cd-835b-2557eddbbf85",
"name": "UPSERT CAMPAIGN ACTIVITY",
"type": "n8n-nodes-base.postgres",
"onError": "continueErrorOutput",
"position": [
980,
960
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "ce_campaign_activity",
"cachedResultName": "ce_campaign_activity"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "outbound_activities",
"cachedResultName": "outbound_activities"
},
"columns": {
"value": {
"id": "={{ $json.id }}",
"email": "={{ $json.email }}",
"status": "={{ $json.status }}",
"website": "={{ $json.email.extractDomain() }}",
"category": "={{ $json.category }}",
"location": "={{ $json.location }}",
"last_name": "={{ $json.last_name }}",
"created_at": "={{ $json.created_at }}",
"first_name": "={{ $json.first_name }}",
"open_count": "={{ $json.open_count }}",
"campaign_id": "={{ $('Loop Over Items').item.json.id }}",
"click_count": "={{ $json.click_count }}",
"company_url": "={{ $json.company_url }}",
"reply_count": "={{ $json.reply_count }}",
"company_name": "={{ $json.company_name }}",
"phone_number": "={{ $json.phone_number }}",
"custom_fields": "={{ JSON.stringify(JSON.parse($json.custom_fields.replace(/\"\"/g, '\"'))) }}",
"is_interested": "={{ $json.is_interested }}",
"is_unsubscribed": "={{ $json.is_unsubscribed }}",
"linkedin_profile": "={{ $json.linkedin_profile }}",
"campaign_lead_map_id": "={{ $json.campaign_lead_map_id }}",
"last_email_sequence_sent": "={{ $json.last_email_sequence_sent }}",
"psg_last_update_timestmap": "={{ $now }}",
"unsubscribed_client_id_map": "={{ $json.unsubscribed_client_id_map }}"
},
"schema": [
{
"id": "id",
"type": "number",
"display": true,
"removed": false,
"required": true,
"displayName": "id",
"defaultMatch": true,
"canBeUsedToMatch": true
},
{
"id": "campaign_lead_map_id",
"type": "number",
"display": true,
"required": false,
"displayName": "campaign_lead_map_id",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "category",
"type": "string",
"display": true,
"required": false,
"displayName": "category",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "is_interested",
"type": "boolean",
"display": true,
"required": false,
"displayName": "is_interested",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "created_at",
"type": "dateTime",
"display": true,
"required": true,
"displayName": "created_at",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "first_name",
"type": "string",
"display": true,
"required": false,
"displayName": "first_name",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "last_name",
"type": "string",
"display": true,
"required": false,
"displayName": "last_name",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "email",
"type": "string",
"display": true,
"required": false,
"displayName": "email",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "phone_number",
"type": "string",
"display": true,
"required": false,
"displayName": "phone_number",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "company_name",
"type": "string",
"display": true,
"required": false,
"displayName": "company_name",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "website",
"type": "string",
"display": true,
"required": false,
"displayName": "website",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "location",
"type": "string",
"display": true,
"required": false,
"displayName": "location",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "custom_fields",
"type": "object",
"display": true,
"required": false,
"displayName": "custom_fields",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "linkedin_profile",
"type": "string",
"display": true,
"required": false,
"displayName": "linkedin_profile",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "company_url",
"type": "string",
"display": true,
"required": false,
"displayName": "company_url",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "is_unsubscribed",
"type": "boolean",
"display": true,
"required": false,
"displayName": "is_unsubscribed",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "unsubscribed_client_id_map",
"type": "object",
"display": true,
"required": false,
"displayName": "unsubscribed_client_id_map",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "last_email_sequence_sent",
"type": "number",
"display": true,
"required": false,
"displayName": "last_email_sequence_sent",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "open_count",
"type": "number",
"display": true,
"required": false,
"displayName": "open_count",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "click_count",
"type": "number",
"display": true,
"required": false,
"displayName": "click_count",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "reply_count",
"type": "number",
"display": true,
"required": false,
"displayName": "reply_count",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "psg_last_update_timestmap",
"type": "dateTime",
"display": true,
"required": false,
"displayName": "psg_last_update_timestmap",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "campaign_id",
"type": "number",
"display": true,
"removed": false,
"required": false,
"displayName": "campaign_id",
"defaultMatch": false,
"canBeUsedToMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
]
},
"options": {
"queryBatching": "independently"
},
"operation": "upsert"
},
"credentials": {},
"typeVersion": 2.5
},
{
"id": "be550807-7ec6-45bc-b522-ae958200e90e",
"name": "HUBSPOT TABLE",
"type": "n8n-nodes-base.postgres",
"position": [
900,
160
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "hubspot",
"cachedResultName": "hubspot"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "outbound_activities",
"cachedResultName": "outbound_activities"
},
"columns": {
"value": {
"campaign_id": "={{ $node['Loop Over Items1'].data.campaign_id}}",
"lifecyclestage": "={{ $json.properties.lifecyclestage.value }}",
"hs_num_open_deals": "={{ $json.properties.hs_num_open_deals.value }}",
"hubspot_company_id": "={{ $json.companyId }}"
},
"schema": [
{
"id": "hubspot_company_id",
"type": "number",
"display": true,
"removed": false,
"required": true,
"displayName": "hubspot_company_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "campaign_id",
"type": "number",
"display": true,
"required": false,
"displayName": "campaign_id",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "lifecyclestage",
"type": "string",
"display": true,
"required": false,
"displayName": "lifecyclestage",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "hs_num_open_deals",
"type": "number",
"display": true,
"required": false,
"displayName": "hs_num_open_deals",
"defaultMatch": false,
"canBeUsedToMatch": false
},
{
"id": "last_engagement_date",
"type": "dateTime",
"display": true,
"removed": true,
"required": false,
"displayName": "last_engagement_date",
"defaultMatch": false,
"canBeUsedToMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"hubspot_company_id"
]
},
"options": {
"queryBatching": "independently"
},
"operation": "upsert"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.5
},
{
"id": "328b900e-8c21-4578-b6a4-8c17fbccca26",
"name": "SEARCH",
"type": "n8n-nodes-base.postgres",
"position": [
-40,
160
],
"parameters": {
"query": "SELECT\n ca.id,\n ca.campaign_id,\n ca.email,\n MIN(ca.first_name) AS first_name,\n MIN(ca.last_name) AS last_name,\n SUM(ca.reply_count) AS reply_count,\n max(hb_lifecyclestage_check_timestamp) as hb_lifecyclestage_check_timestamp,\n CASE\n -- Check if there is a comma and handle the extraction first\n WHEN MIN(ca.linkedin_profile) LIKE '%,%' \n THEN \n -- Replace /sales/people/ with /in/ on the extracted part before the comma\n REPLACE(LEFT(MIN(ca.linkedin_profile), POSITION(',' IN MIN(ca.linkedin_profile)) - 1), '/sales/people/', '/in/')\n ELSE \n -- For profiles without a comma, check for the replacement directly\n REPLACE(MIN(ca.linkedin_profile), '/sales/people/', '/in/')\n END AS linkedin_profile,\n MAX(ca.company_url) AS company_profile,\n -- Extracting domain from email to create the website column\n SUBSTRING(ca.email FROM POSITION('@' IN ca.email) + 1) AS website,\n c.created_at,\n c.updated_at,\n c.status,\n c.name\nFROM\n outbound_activities.ce_campaign_activity ca\nJOIN\n outbound_activities.ce_campaign c ON ca.campaign_id = c.campaign_id\n--left join outbound_activities.hubspot hb on \n\nWHERE \n hb_lifecyclestage_check_timestamp IS NULL \n OR hb_lifecyclestage_check_timestamp < NOW() - INTERVAL '24 hours'\n\n \nGROUP BY\n ca.id,\n ca.campaign_id,\n ca.email,\n c.created_at,\n c.updated_at,\n c.status,\n c.name\n\n\nlimit 5000",
"options": {},
"operation": "executeQuery"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.5
},
{
"id": "c403ef52-894d-476a-aaba-6527c7cb2184",
"name": "Postgres1",
"type": "n8n-nodes-base.postgres",
"position": [
640,
380
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "ce_campaign_activity",
"cachedResultName": "ce_campaign_activity"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "outbound_activities",
"cachedResultName": "outbound_activities"
},
"columns": {
"value": {
"id": "={{ $('Loop Over Items1').item.json.id }}",
"hb_lifecyclestage_check_timestamp": "={{ $now }}"
},
"schema": [
{
"id": "id",
"type": "number",
"display": true,
"removed": false,
"required": true,
"displayName": "id",
"defaultMatch": true,
"canBeUsedToMatch": true
},
{
"id": "campaign_lead_map_id",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "campaign_lead_map_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "category",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "is_interested",
"type": "boolean",
"display": true,
"removed": true,
"required": false,
"displayName": "is_interested",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "created_at",
"type": "dateTime",
"display": true,
"removed": true,
"required": true,
"displayName": "created_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "first_name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "first_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "last_name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "last_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "email",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "phone_number",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "phone_number",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "company_name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "company_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "website",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "website",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "location",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "location",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "custom_fields",
"type": "object",
"display": true,
"removed": true,
"required": false,
"displayName": "custom_fields",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "linkedin_profile",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "linkedin_profile",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "company_url",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "company_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "is_unsubscribed",
"type": "boolean",
"display": true,
"removed": true,
"required": false,
"displayName": "is_unsubscribed",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "unsubscribed_client_id_map",
"type": "object",
"display": true,
"removed": true,
"required": false,
"displayName": "unsubscribed_client_id_map",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "last_email_sequence_sent",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "last_email_sequence_sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "open_count",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "open_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "click_count",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "click_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "reply_count",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "reply_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "psg_last_update_timestmap",
"type": "dateTime",
"display": true,
"removed": true,
"required": false,
"displayName": "psg_last_update_timestmap",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "campaign_id",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "campaign_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "hb_lifecyclestage_check_timestamp",
"type": "dateTime",
"display": true,
"required": false,
"displayName": "hb_lifecyclestage_check_timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
]
},
"options": {},
"operation": "update"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.5
},
{
"id": "671f168b-a720-42e6-964d-a7f2871d2d6e",
"name": "UPDATE HUBSPOT ACTIVITY TABLE",
"type": "n8n-nodes-base.postgres",
"position": [
1120,
160
],
"parameters": {
"table": {
"__rl": true,
"mode": "list",
"value": "ce_campaign_activity",
"cachedResultName": "ce_campaign_activity"
},
"schema": {
"__rl": true,
"mode": "list",
"value": "outbound_activities",
"cachedResultName": "outbound_activities"
},
"columns": {
"value": {
"id": "={{ $('Loop Over Items1').item.json.id }}",
"hb_lifecyclestage_check_timestamp": "={{ $now }}"
},
"schema": [
{
"id": "id",
"type": "number",
"display": true,
"removed": false,
"required": true,
"displayName": "id",
"defaultMatch": true,
"canBeUsedToMatch": true
},
{
"id": "campaign_lead_map_id",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "campaign_lead_map_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "category",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "is_interested",
"type": "boolean",
"display": true,
"removed": true,
"required": false,
"displayName": "is_interested",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "created_at",
"type": "dateTime",
"display": true,
"removed": true,
"required": true,
"displayName": "created_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "first_name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "first_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "last_name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "last_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "email",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "phone_number",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "phone_number",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "company_name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "company_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "website",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "website",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "location",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "location",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "custom_fields",
"type": "object",
"display": true,
"removed": true,
"required": false,
"displayName": "custom_fields",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "linkedin_profile",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "linkedin_profile",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "company_url",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "company_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "is_unsubscribed",
"type": "boolean",
"display": true,
"removed": true,
"required": false,
"displayName": "is_unsubscribed",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "unsubscribed_client_id_map",
"type": "object",
"display": true,
"removed": true,
"required": false,
"displayName": "unsubscribed_client_id_map",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "last_email_sequence_sent",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "last_email_sequence_sent",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "open_count",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "open_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "click_count",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "click_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "reply_count",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "reply_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "psg_last_update_timestmap",
"type": "dateTime",
"display": true,
"removed": true,
"required": false,
"displayName": "psg_last_update_timestmap",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "campaign_id",
"type": "number",
"display": true,
"removed": true,
"required": false,
"displayName": "campaign_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "hb_lifecyclestage_check_timestamp",
"type": "dateTime",
"display": true,
"required": false,
"displayName": "hb_lifecyclestage_check_timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
]
},
"options": {},
"operation": "update"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"typeVersion": 2.5
},
{
"id": "6ebe6482-0f31-465a-8532-abaf3822ad72",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-140,
-60
],
"parameters": {
"color": 3,
"width": 1531.405758029468,
"height": 669.051063941859,
"content": "## HUBSPOT LIFECYCLESTAGE (LEAD STATUS)"
},
"typeVersion": 1
},
{
"id": "31ea75c2-a228-4390-b125-8f2ac0b96a07",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-140,
760
],
"parameters": {
"color": 3,
"width": 1831,
"height": 669,
"content": "## SMARTLEAD CAMPAIGN DATA"
},
"typeVersion": 1
},
{
"id": "8d7e4883-74e2-4758-b2d9-504eb7301cbd",
"name": "SET SMARTLEAD API KEY",
"type": "n8n-nodes-base.set",
"position": [
-1040,
980
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "7f81531d-f76f-42c7-b536-2b7b70563e12",
"name": "API KEY",
"type": "string",
"value": "<< ADD YOUR API KEY HERE >>"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "1742845b-2ce5-4184-a7b0-6f5606714fcb",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1100,
780
],
"parameters": {
"height": 400,
"content": "## Search for your smartlead API key [here](https://app.smartlead.ai/app/settings/profile)"
},
"typeVersion": 1
},
{
"id": "e10205a7-3859-4a31-85ba-59c5cc0b69f7",
"name": "Postgres",
"type": "n8n-nodes-base.postgres",
"position": [
-40,
1700
],
"parameters": {
"query": "SELECT \n h.campaign_id,\n c.status,\n c.name,\n COUNT(DISTINCT h.hubspot_company_id) AS total_companies,\n SUM(CASE WHEN h.lifecyclestage = 'lead' AND h.hs_num_open_deals != 0 THEN 1 ELSE 0 END) AS lead_count,\n SUM(CASE WHEN h.lifecyclestage = 'marketingqualifiedlead' AND h.hs_num_open_deals != 0 THEN 1 ELSE 0 END) AS marketingqualifiedlead_count,\n SUM(CASE WHEN h.lifecyclestage = 'salesqualifiedlead' AND h.hs_num_open_deals != 0 THEN 1 ELSE 0 END) AS salesqualifiedlead_count,\n SUM(CASE WHEN h.lifecyclestage = 'opportunity' AND h.hs_num_open_deals != 0 THEN 1 ELSE 0 END) AS opportunity_count,\n SUM(CASE WHEN h.lifecyclestage = 'customer' AND h.hs_num_open_deals != 0 THEN 1 ELSE 0 END) AS customer_count,\n SUM(CASE WHEN h.lifecyclestage = '140669943' AND h.hs_num_open_deals != 0 THEN 1 ELSE 0 END) AS lifecyclestage_140669943_count,\n SUM(CASE WHEN h.lifecyclestage = '140669942' AND h.hs_num_open_deals != 0 THEN 1 ELSE 0 END) AS lifecyclestage_140669942_count\nFROM \n outbound_activities.hubspot h\nJOIN \n outbound_activities.ce_campaign c ON h.campaign_id = c.campaign_id\nGROUP BY \n h.campaign_id, c.status, c.name",
"options": {
"queryBatching": "independently"
},
"operation": "executeQuery"
},
"credentials": {
"postgres": {
"name": "<your credential>"
}
},
"retryOnFail": true,
"typeVersion": 2.5
},
{
"id": "19a80be4-f81f-44f7-8108-a20f6af8e315",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1300,
1340
],
"parameters": {
"width": 740,
"height": 400,
"content": "## POSTGRES INSTALATION [Guide](https://github.com/wukimidaire/postgres_table_templates)\n\n## Follow this step by step guide, focus on the next 3 table creations for this flow:\n## - ce_campaign_activity\n## - ce_campaign\n## - hubspot"
},
"typeVersion": 1
},
{
"id": "7bc235d2-65c8-41fd-b429-26b2422cbfa8",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-120,
1580
],
"parameters": {
"color": 3,
"width": 1060,
"height": 1313.3157639300548,
"content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Campaign Analytics Report Documentation\n\nOverview\n\nThis report provides a high-level summary of campaign performance, designed to help stakeholders quickly assess the outcomes of marketing or sales campaigns. It includes data on campaign activity, targeted audiences, and progression metrics, allowing for a holistic view of campaign effectiveness.\n\n## Key Metrics\n\n\t1\t**Campaign Identification and Status**\n\n \u2022\tCampaign ID: A unique identifier assigned to each campaign for tracking purposes.\n\t\u2022\tStatus: Indicates the current state of the campaign:\n\t\u2022\tActive: Campaign is ongoing.\n\t\u2022\tPaused: Campaign is temporarily on hold.\n\t\u2022\tArchived: Campaign has concluded.\n\n2 **Targeting and Reach**\n\n\t\u2022\tTotal Companies: Number of companies targeted within the campaign scope.\n\n\n3\t**Pipeline Metrics**\n\n\t\u2022\tLead Count: Total number of leads generated by the campaign.\n\t\u2022\tMarketing Qualified Leads (MQLs): Leads that meet predefined marketing qualification criteria.\n\t\u2022\tSales Qualified Leads (SQLs): Leads that are validated as sales-ready by the team.\n\t\u2022\tOpportunities: Potential deals created from campaign engagement.\n\t\u2022\tCustomers: Number of deals successfully closed, converting leads into customers.\n\n\n4\t**Lifecycle Stages**\n\n\t\u2022\tLifecycle Stage Metrics: Counts of entities (e.g., leads, opportunities, or customers) at specific lifecycle stages. These stages represent the journey from lead generation to conversion.\n\n\n\n## How to Use This Report\n\n\t\u2022\t**Evaluate Campaign Success**: Compare metrics like total companies, leads, and customers to understand campaign impact.\n\t\u2022\t**Understand Pipeline Health**: Analyze how many entities progress through the funnel (e.g., from MQL to SQL to Opportunity).\n\t\u2022\t**Monitor Campaign Status**: Use the status column to focus on active campaigns or review the outcomes of archived ones.\n\t\u2022\t**Assess Engagement**: Check opportunity and customer counts to gauge how effective the campaign is in driving conversions."
},
"typeVersion": 1
},
{
"id": "0af663c4-faa9-49ae-a5d3-3bcb6ea7888a",
"name": "Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
180,
1700
],
"parameters": {
"columns": {
"value": {
"name": "={{ $json.name }}",
"status": "={{ $json.status }}",
"lead_count": "={{ $json.lead_count }}",
"campaign_id": "={{ $json.company_id }}",
"customer_count": "={{ $json.customer_count\n}}\n",
"total_companies": "={{ $json.total_companies }}",
"opportunity_count": "={{ $json.opportunity_count\n }}",
"salesqualifiedlead_count": "={{ $json.salesqualifiedlead_count }}",
"marketingqualifiedlead_count": "={{ $json.marketingqualifiedlead_count }}",
"lifecyclestage_140669942_count": "={{ $json.lifecyclestage_140669942_count\n}}\n",
"lifecyclestage_140669943_count": "={{ $json.lifecyclestage_140669943_count\n}}\n"
},
"schema": [
{
"id": "campaign_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "campaign_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "name",
"type": "string",
"display": true,
"required": false,
"displayName": "name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "total_companies",
"type": "string",
"display": true,
"required": false,
"displayName": "total_companies",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "lead_count",
"type": "string",
"display": true,
"required": false,
"displayName": "lead_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "marketingqualifiedlead_count",
"type": "string",
"display": true,
"required": false,
"displayName": "marketingqualifiedlead_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "salesqualifiedlead_count",
"type": "string",
"display": true,
"required": false,
"displayName": "salesqualifiedlead_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "opportunity_count",
"type": "string",
"display": true,
"required": false,
"displayName": "opportunity_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "customer_count",
"type": "string",
"display": true,
"required": false,
"displayName": "customer_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "lifecyclestage_140669943_count",
"type": "string",
"display": true,
"required": false,
"displayName": "lifecyclestage_140669943_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "lifecyclestage_140669942_count",
"type": "string",
"display": true,
"required": false,
"displayName": "lifecyclestage_140669942_count",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"campaign_id"
]
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kG5uXCzOJdUTapA6p-IbH3D8sjpGZ5MQm_IhhvPvIGE/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1kG5uXCzOJdUTapA6p-IbH3D8sjpGZ5MQm_IhhvPvIGE",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kG5uXCzOJdUTapA6p-IbH3D8sjpGZ5MQm_IhhvPvIGE/edit?usp=drivesdk",
"cachedResultName": "Smartlead Reporting - TEMPLATE"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.5
}
],
"connections": {
"If": {
"main": [
[
{
"node": "HUBSPOT TABLE",
"type": "main",
"index": 0
}
],
[
{
"node": "Postgres1",
"type": "main",
"index": 0
}
]
]
},
"Code": {
"main": [
[
{
"node": "UPSERT CAMPAIGN ACTIVITY",
"type": "main",
"index": 0
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.
googleSheetsOAuth2ApihubspotOAuth2Apipostgres
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
How this works
This workflow automates the synchronisation of marketing campaign data from HubSpot to a Postgres database, ensuring your records stay current without manual effort and freeing up time for strategic analysis. It suits marketing teams or data analysts managing customer engagement metrics who need reliable, up-to-date storage for reporting. The key step involves looping through batches of campaigns fetched via HTTP requests, then updating the Postgres database with precise details like performance stats.
Use this when you run regular HubSpot campaigns and require automated backups to Postgres for custom queries or BI tools, especially on a daily cron schedule to capture fresh data. Avoid it for one-off imports or if your volume exceeds thousands of records daily, as it may need scaling. Common variations include adding Google Sheets export for quick dashboards or filtering specific campaign types before the Postgres update.
About this workflow
Code Postgres. Uses httpRequest, splitInBatches, postgres, hubspot. Scheduled trigger; 23 nodes.
Source: https://github.com/Zie619/n8n-workflows — 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 monitors customer health by combining payment behavior, complaint signals, and AI-driven feedback analysis. It runs on daily and weekly schedules to evaluate risk levels, escalate high-r
Automate your cold email outreach with this 3-stage workflow that sends emails, triggers follow-ups after 3 days, and syncs responses to HubSpot CRM automatically. Uses: n8n, Postgres/Supabase, Resend
Continuous monitoring: Real-time surveillance of supplier performance, financial health, and operational status Risk scoring: AI-powered assessment of supplier risks across multiple dimensions (financ
Regulatory monitoring: Continuously tracks changes in laws, regulations, and compliance requirements across multiple jurisdictions Contract analysis: AI-powered review of existing contracts to identif
Stop manually checking dozens of career pages. This workflow runs every morning, hits the public APIs of 8+ ATS platforms and job boards, normalizes every listing into a single clean schema, and syncs