This workflow corresponds to n8n.io template #17788 — we link there as the canonical source.
This workflow follows the Google Drive → Google Sheets 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 →
{
"name": "Generate real estate listing flyers from Google Sheets and Google Drive with Canva",
"nodes": [
{
"id": "81017b41-a3d2-4448-b131-b52f05e620e8",
"name": "About this template",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
96
],
"parameters": {
"width": 460,
"height": 956,
"content": "# \ud83c\udfe0 Generate real estate listing flyers from Google Sheets and Google Drive with Canva\n\n**Who's it for**\nReal estate agencies and marketing teams on Canva Enterprise that produce listing flyers at scale. (Note that it can also be extended to users outside of this industry!)\n\n**How it works**\n\n1. A real estate agent adds a new row to a Google Sheet (listing ID, address, price, beds, baths, and agent details) then sets the `ready` column to *`YES`*.\n2. The workflow finds the listing photo in a Google Drive folder, matching the file whose name starts with the listing ID (e.g. `RE-1024.jpg`).\n3. The photo is uploaded to Canva as an asset.\n4. Canva Data Autofill populates your Canva brand template with the spreadsheet data, and the finished design link is written back to the Google Sheet.\n\n**Setup**\n\n- [ ] Create a Google Sheet with columns: `ready`, `listing_id`, `address`, `price`, `beds`, `baths`, `agent_name`, `agent_phone`, `design_url`, `status`.\n- [ ] Share a Google Drive photo folder as \u201cAnyone with the link \u2192 Viewer\u201d (Canva downloads the image by URL).\n- [ ] In Canva, create a brand template with a dataset: `property_photo` (image) and `address`, `price`, `beds_baths`, `agent_name`, `agent_phone` (text).\n- [ ] Enter your brand template ID and Drive folder ID in **Workflow configuration**.\n- [ ] Connect your Google and Canva credentials.\n\n**Requirements**\n- Canva Enterprise account (Data Autofill is Enterprise-only)\n- The **verified** community node `@canva/n8n-nodes-canva` (officially provided by Canva)."
},
"typeVersion": 1
},
{
"id": "01e0182c-65ec-4687-a7c9-69e326e26a9c",
"name": "Note \u2014 trigger",
"type": "n8n-nodes-base.stickyNote",
"position": [
640,
96
],
"parameters": {
"color": 7,
"width": 496,
"height": 948,
"content": "## Google Sheets trigger\n\nThe Google Sheets trigger normally fires on **every cell edit**, usually before the row is finished.\n\nThis template watches **only the `ready` column** (trigger option \u201cColumns to Watch\u201d), and the IF node only lets a row through when `ready` is exactly `YES`.\n\nAfter the design is created, the workflow sets `ready` to `DONE`, so a row is never processed twice. To re-run a listing, set `ready` back to `YES`."
},
"typeVersion": 1
},
{
"id": "5c56c14c-8907-434d-a454-9af138b2839b",
"name": "Note \u2014 photo search",
"type": "n8n-nodes-base.stickyNote",
"position": [
1712,
96
],
"parameters": {
"color": 7,
"width": 428,
"height": 948,
"content": "## Find the listing photo\n\nSearches the configured Google Drive folder for a file whose name begins with the listing `ID`.\n\nThe folder must be shared as **\u201cAnyone with the link \u2192 Viewer\u201d** so Canva can access and download the image. If no matching photo is found, the workflow updates the row's `status` as `NO_PHOTO` instead of failing."
},
"typeVersion": 1
},
{
"id": "40cefae7-8773-4d94-a8c2-aa0c252b5443",
"name": "Note \u2014 Canva",
"type": "n8n-nodes-base.stickyNote",
"position": [
2224,
96
],
"parameters": {
"color": 7,
"width": 492,
"height": 528,
"content": "## Upload & autofill\n\nUploads the listing photo to Canva, then uses Data Autofill to create a new design from your brand template using the listing details.\n\nThe field names in the Data Autofill node must exactly match the dataset field names in your brand template.\n\nLearn more in the [Autofill and Brand Templates guide](https://www.canva.dev/docs/connect/autofill-guide/)."
},
"typeVersion": 1
},
{
"id": "dc61489d-c2a3-4334-b0a9-8e98fb7660fc",
"name": "Note \u2014 write back",
"type": "n8n-nodes-base.stickyNote",
"position": [
2800,
96
],
"parameters": {
"color": 7,
"width": 420,
"height": 500,
"content": "## Write results back\n\nThe row is updated with the Canva design URL:\n\n`ready`: *`DONE`*\n`design_url`: *`{{URL_FROM_PREVIOUS_STEP}}`*\n`status`: *`DESIGN_WITH_PHOTO`*"
},
"typeVersion": 1
},
{
"id": "cfcd0952-c488-4973-bd01-cb7e5967c081",
"name": "Row marked ready?",
"type": "n8n-nodes-base.if",
"position": [
944,
688
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-ready-01",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ ($json.ready ?? '').toString().trim().toUpperCase() }}",
"rightValue": "YES"
}
]
}
},
"typeVersion": 2
},
{
"id": "09e76b08-7892-41c8-bf15-987c320490b2",
"name": "Workflow configuration",
"type": "n8n-nodes-base.set",
"position": [
1360,
672
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "cfg-0001",
"name": "brand_template_id",
"type": "string",
"value": "YOUR_BRAND_TEMPLATE_ID"
},
{
"id": "cfg-0002",
"name": "drive_folder_id",
"type": "string",
"value": "YOUR_DRIVE_FOLDER_ID"
},
{
"id": "cfg-0003",
"name": "spreadsheet_id",
"type": "string",
"value": "={{ ($('On Sheet row update').params.documentId.value || '').toString().match(/[-\\w]{25,}/)?.[0] }}"
},
{
"id": "cfg-0004",
"name": "sheet_id",
"type": "string",
"value": "={{ $('On Sheet row update').params.sheetName.value }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "68a7cdc5-e284-4c33-8586-e6ecf71f1ec0",
"name": "Upload photo to Canva",
"type": "@canva/n8n-nodes-canva.canva",
"position": [
2304,
416
],
"parameters": {
"url": "={{ 'https://lh3.googleusercontent.com/d/' + $json.id }}",
"name": "={{ $('Workflow configuration').item.json.listing_id + ' \u2014 listing photo' }}",
"maxWait": 120,
"resource": "asset",
"operation": "upload"
},
"typeVersion": 1
},
{
"id": "58178e40-1875-4073-9e78-40979350e7e3",
"name": "Write design link to sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2944,
416
],
"parameters": {
"columns": {
"value": {
"ready": "DONE",
"status": "DESIGN_WITH_PHOTO",
"design_url": "={{ $json.job.result.design.url }}",
"listing_id": "={{ $('Workflow configuration').item.json.listing_id }}"
},
"schema": [
{
"id": "ready",
"type": "string",
"display": true,
"required": false,
"displayName": "ready",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "listing_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "listing_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "address",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "price",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "price",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beds",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beds",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "baths",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "baths",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "agent_name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "agent_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "agent_phone",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "agent_phone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "design_url",
"type": "string",
"display": true,
"required": false,
"displayName": "design_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"listing_id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "={{ $('Workflow configuration').item.json.sheet_id }}"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Workflow configuration').item.json.spreadsheet_id }}"
}
},
"typeVersion": 4.5
},
{
"id": "47f771c0-400e-4a99-b89d-a15dbe2489fa",
"name": "Mark row as missing photo",
"type": "n8n-nodes-base.googleSheets",
"position": [
2304,
864
],
"parameters": {
"columns": {
"value": {
"ready": "DONE",
"status": "NO_PHOTO",
"listing_id": "={{ $('Workflow configuration').item.json.listing_id }}"
},
"schema": [
{
"id": "ready",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "ready",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "listing_id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "listing_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "address",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "price",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "price",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "beds",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "beds",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "baths",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "baths",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "agent_name",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "agent_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "agent_phone",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "agent_phone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "design_url",
"type": "string",
"display": true,
"removed": true,
"required": false,
"displayName": "design_url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "row_number",
"type": "number",
"display": true,
"removed": true,
"readOnly": true,
"required": false,
"displayName": "row_number",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"listing_id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "update",
"sheetName": {
"__rl": true,
"mode": "id",
"value": "={{ $('Workflow configuration').item.json.sheet_id }}"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Workflow configuration').item.json.spreadsheet_id }}"
}
},
"typeVersion": 4.5
},
{
"id": "39433dca-06f9-4c2f-8e24-27b475069938",
"name": "Note \u2014 configuration",
"type": "n8n-nodes-base.stickyNote",
"position": [
1200,
96
],
"parameters": {
"color": 7,
"width": 432,
"height": 944,
"content": "## Workflow configuration\n\nThis is where you'll set the workflow's main variables:\n\n`brand_template_id`: It is the ID of the brand template you created (with your Entreprise plan), containing the dataset fields mentioned on the main yellow sticky note. You can find it in the URL: *`https://www.canva.com/brand/brand-templates/X`*\n\n`drive_folder_id`: It is the ID of the Google Drive folder containing the assets you'll want to search into. You can also find it in the URL: *`https://drive.google.com/drive/u/0/folders/X`*\n\n`spreadsheet_id` / `sheet_id`: derived **automatically** from the trigger's settings \u2014 leave them as they are. Every later node reads the spreadsheet from here, so the sheet is only ever configured once, in the trigger.\n"
},
"typeVersion": 1
},
{
"id": "1043a0ce-071e-41ef-bea7-998342ab77b7",
"name": "Photo found?",
"type": "n8n-nodes-base.if",
"position": [
1968,
672
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cond-photo-01",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ ($json.id ?? '') !== '' }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2
},
{
"id": "a3b9b28c-d108-4b39-b501-1d0901f1e675",
"name": "Find photo in Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
1776,
672
],
"parameters": {
"limit": 1,
"filter": {
"folderId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.drive_folder_id }}"
},
"whatToSearch": "files"
},
"options": {
"fields": [
"id",
"name",
"webViewLink"
]
},
"resource": "fileFolder",
"queryString": "={{ $json.listing_id }}"
},
"typeVersion": 3,
"alwaysOutputData": true
},
{
"id": "d0ac976a-049b-4cc9-b75e-3628dff8a28d",
"name": "Create design from brand template",
"type": "@canva/n8n-nodes-canva.canva",
"position": [
2528,
416
],
"parameters": {
"data": "={{ JSON.stringify({\n property_photo: { type: 'image', asset_id: $json.job.asset.id },\n address: { type: 'text', text: $('Workflow configuration').item.json.address },\n price: { type: 'text', text: $('Workflow configuration').item.json.price.toString() },\n beds_baths: { type: 'text', text: $('Workflow configuration').item.json.beds + ' bed \u00b7 ' + $('Workflow configuration').item.json.baths + ' bath' },\n agent_name: { type: 'text', text: $('Workflow configuration').item.json.agent_name },\n agent_phone: { type: 'text', text: $('Workflow configuration').item.json.agent_phone.toString() }\n}) }}",
"title": "={{ 'Listing flyer \u2014 ' + $('Workflow configuration').item.json.listing_id + ' ' + $('Workflow configuration').item.json.address }}",
"resource": "autofill",
"brandTemplateId": "={{ $('Workflow configuration').item.json.brand_template_id }}"
},
"typeVersion": 1
},
{
"id": "da8fef64-1ca8-4fe0-8508-40e6bd08cf65",
"name": "Note \u2014 write back (no photo)",
"type": "n8n-nodes-base.stickyNote",
"position": [
2224,
640
],
"parameters": {
"color": 7,
"width": 484,
"height": 404,
"content": "## Write results back\n\nThe row is updated without creating a Canva design:\n\n`ready`: *`DONE`*\n`status`: *`NO_PHOTO`*"
},
"typeVersion": 1
},
{
"id": "5fe307ed-8fa7-41a2-8b9d-81919214e857",
"name": "On Sheet row update",
"type": "n8n-nodes-base.googleSheetsTrigger",
"position": [
720,
688
],
"parameters": {
"options": {
"columnsToWatch": [
"ready"
]
},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "YOUR_SHEET_ID"
},
"documentId": {
"__rl": true,
"mode": "url",
"value": "https://docs.google.com/spreadsheets/d/YOUR_DOCUMENT_ID/edit"
}
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"connections": {
"Photo found?": {
"main": [
[
{
"node": "Upload photo to Canva",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark row as missing photo",
"type": "main",
"index": 0
}
]
]
},
"Row marked ready?": {
"main": [
[
{
"node": "Workflow configuration",
"type": "main",
"index": 0
}
]
]
},
"Find photo in Drive": {
"main": [
[
{
"node": "Photo found?",
"type": "main",
"index": 0
}
]
]
},
"On Sheet row update": {
"main": [
[
{
"node": "Row marked ready?",
"type": "main",
"index": 0
}
]
]
},
"Upload photo to Canva": {
"main": [
[
{
"node": "Create design from brand template",
"type": "main",
"index": 0
}
]
]
},
"Workflow configuration": {
"main": [
[
{
"node": "Find photo in Drive",
"type": "main",
"index": 0
}
]
]
},
"Create design from brand template": {
"main": [
[
{
"node": "Write design link to sheet",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow watches a Google Sheet for listings marked ready, finds the matching photo in Google Drive, uploads it to Canva, and uses Canva Data Autofill to generate a listing flyer from a brand template, then writes the finished design URL back to the sheet. Triggers when the…
Source: https://n8n.io/workflows/17788/ — 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.
Stickynote Workflow. Uses googleTranslate, googleSheetsTrigger, googleDrive, httpRequest. Event-driven trigger; 22 nodes.
This workflow watches a Google Sheets worksheet for new client rows, creates (or reuses) a matching client folder structure in Google Drive, shares the folder with one or more client email addresses,
This workflow automatically generates a branded PDF invoice from data in Google Sheets and saves it to Google Drive. No manual document editing required.
[](https://youtu.be/Ft3c_NPRlI8)
PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.