AutomationFlowsData & Sheets › Generate Bulk Certificates From Google Sheets and Google Slides

Generate Bulk Certificates From Google Sheets and Google Slides

ByDiego Alejandro Parrás @diegoalejandroparras on n8n.io

Categories: Productivity, Education, Google, Automation

Event trigger★★★★☆ complexity15 nodesGoogle SheetsHTTP RequestGoogle Drive
Data & Sheets Trigger: Event Nodes: 15 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #13219 — 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 →

Download .json
{
  "id": "UwWFNPUauG6I7NdKhcV1V",
  "name": "Bulk certificate generator from Google Sheets and Slides",
  "tags": [],
  "nodes": [
    {
      "id": "f352d49c-d9bc-49fa-8b0a-c43a94d321fa",
      "name": "When clicking 'Test workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -272,
        -32
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "4651f9ff-07a3-4857-9d69-06cf864315e5",
      "name": "Read Unprocessed Recipients",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -48,
        -32
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "FALSE",
              "lookupColumn": "Processed"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "5b34aeac-f173-4c22-8826-930bb392182f",
      "name": "Process One at a Time",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        224,
        -32
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "0d054ec2-6ac2-43f9-a5f7-3ce5a4399556",
      "name": "Copy Slides Template",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        480,
        -16
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/drive/v3/files/YOUR_TEMPLATE_SLIDES_ID/copy",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ name: 'Certificate_' + $json['CertificateID'] }) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleDriveOAuth2Api"
      },
      "typeVersion": 4.2
    },
    {
      "id": "546fe323-348e-4345-9658-abb66e898a19",
      "name": "Replace Template Placeholders",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        688,
        -16
      ],
      "parameters": {
        "url": "=https://slides.googleapis.com/v1/presentations/{{ $json.id }}:batchUpdate",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"requests\": [\n    {\n      \"replaceAllText\": {\n        \"containsText\": { \"text\": \"{{name}}\", \"matchCase\": false },\n        \"replaceText\": \"{{ $('Process One at a Time').item.json.Name }}\"\n      }\n    },\n    {\n      \"replaceAllText\": {\n        \"containsText\": { \"text\": \"{{date}}\", \"matchCase\": false },\n        \"replaceText\": \"{{ $('Process One at a Time').item.json.Date }}\"\n      }\n    },\n    {\n      \"replaceAllText\": {\n        \"containsText\": { \"text\": \"{{certificateid}}\", \"matchCase\": false },\n        \"replaceText\": \"{{ $('Process One at a Time').item.json['CertificateID'] }}\"\n      }\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleSlidesOAuth2Api"
      },
      "typeVersion": 4.2
    },
    {
      "id": "404a9f32-2653-46f1-ae0f-da5e517b85f1",
      "name": "Export to PDF",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        912,
        -16
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/drive/v3/files/{{ $('Copy Slides Template').item.json.id }}/export?mimeType=application/pdf",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        },
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleSlidesOAuth2Api"
      },
      "typeVersion": 4.2
    },
    {
      "id": "e1d0a513-024c-49c5-b5b0-6af8145ccf09",
      "name": "Save PDF to Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        1152,
        -16
      ],
      "parameters": {
        "name": "={{ $('Process One at a Time').item.json['CertificateID']}}.pdf",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_OUTPUT_FOLDER_ID"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "beda0ef7-7376-431c-b753-2565efa28f5f",
      "name": "Mark as Processed",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1376,
        -16
      ],
      "parameters": {
        "columns": {
          "value": {
            "DriveLink": "={{ $('Save PDF to Drive').item.json.webViewLink }}",
            "Processed": "TRUE",
            "CertificateID": "={{ $('Read Unprocessed Recipients').item.json['CertificateID'] }}"
          },
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "CertificateID"
          ]
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "e85e5469-bfeb-43d2-a9d1-e478f06695a6",
      "name": "Delete Temporary Slide",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1600,
        -16
      ],
      "parameters": {
        "url": "=https://www.googleapis.com/drive/v3/files/{{ $('Copy Slides Template').item.json.id }}",
        "method": "DELETE",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "googleSlidesOAuth2Api"
      },
      "typeVersion": 4.2
    },
    {
      "id": "420a078e-5d83-416f-9b23-0c16e89222d3",
      "name": "Wait 2s (Rate Limit)",
      "type": "n8n-nodes-base.wait",
      "position": [
        1824,
        -16
      ],
      "parameters": {
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "4cfca671-cf3d-48c5-905a-3f86db1d4433",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -928,
        -240
      ],
      "parameters": {
        "width": 560,
        "height": 550,
        "content": "## How it works\nThis workflow generates personalized PDF certificates in bulk using Google Sheets as the data source and Google Slides as the template engine.\n\n1. Reads recipient data from a Google Sheet (only rows where Processed = FALSE)\n2. For each recipient, copies your Slides template and replaces placeholders with actual values\n3. Exports the personalized slide as a PDF and saves it to Google Drive\n4. Updates the spreadsheet with the Drive link and marks the row as processed\n5. Cleans up by deleting the temporary slide copy\n\n## Setup steps\n1. **Google Sheet**: Create a sheet with columns: Name, Date, CertificateID, Processed, DriveLink. Set Processed to FALSE for new entries.\n2. **Slides Template**: Create a template with placeholders: {{name}}, {{date}}, {{certificateid}}\n3. **Credentials**: Connect Google Sheets, Drive, and Slides OAuth2 credentials\n4. **Configure IDs**: Replace YOUR_GOOGLE_SHEET_ID, YOUR_TEMPLATE_SLIDES_ID, and YOUR_OUTPUT_FOLDER_ID in the nodes\n5. **Test**: Run with one row first to verify everything works correctly"
      },
      "typeVersion": 1
    },
    {
      "id": "2da79aa7-186f-4239-9946-611867eb56de",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -288,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 652,
        "height": 336,
        "content": "### \ud83d\udce5 Data Input\nReads recipients from Google Sheets and processes them one at a time to avoid API rate limits."
      },
      "typeVersion": 1
    },
    {
      "id": "8b5724f3-07ab-4e46-ad57-b2d9730ea818",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 680,
        "height": 336,
        "content": "### \ud83c\udfa8 Certificate Generation\nCopies the Slides template, replaces placeholders with recipient data, and exports as PDF."
      },
      "typeVersion": 1
    },
    {
      "id": "73124c2f-6c78-49f3-8571-c3e59487c0c4",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1104,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 450,
        "height": 336,
        "content": "### \ud83d\udcbe Save & Update\nSaves the PDF to Drive and updates the spreadsheet with the file link."
      },
      "typeVersion": 1
    },
    {
      "id": "28057c2a-b7e1-4228-abb0-36b5a76af4d0",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1584,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 414,
        "height": 336,
        "content": "### \ud83e\uddf9 Cleanup & Loop\nDeletes temporary files and waits 2 seconds before processing the next recipient."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "6a20ac22-9b29-452b-a4c3-0447ac481c28",
  "connections": {
    "Export to PDF": {
      "main": [
        [
          {
            "node": "Save PDF to Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark as Processed": {
      "main": [
        [
          {
            "node": "Delete Temporary Slide",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save PDF to Drive": {
      "main": [
        [
          {
            "node": "Mark as Processed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Copy Slides Template": {
      "main": [
        [
          {
            "node": "Replace Template Placeholders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 2s (Rate Limit)": {
      "main": [
        [
          {
            "node": "Process One at a Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process One at a Time": {
      "main": [
        [],
        [
          {
            "node": "Copy Slides Template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Delete Temporary Slide": {
      "main": [
        [
          {
            "node": "Wait 2s (Rate Limit)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Unprocessed Recipients": {
      "main": [
        [
          {
            "node": "Process One at a Time",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Replace Template Placeholders": {
      "main": [
        [
          {
            "node": "Export to PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking 'Test workflow'": {
      "main": [
        [
          {
            "node": "Read Unprocessed Recipients",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Categories: Productivity, Education, Google, Automation

Source: https://n8n.io/workflows/13219/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.

Google Sheets, HTTP Request, @N Octo N/N8N Nodes Json Database +3
Data & Sheets

The workflow automates the process of gathering extensive keyword data for a "Main Keyword." It starts by reading initial parameters from a Google Sheets template, creates a new dedicated Google Sheet

Google Sheets, Google Drive, HTTP Request
Data & Sheets

🔥 March Sale – n8n Community Members Get ideoGener8r for Just $27! (Reg. $47) Use Coupon Code: (Valid until 3/31/2025 for n8n community members)

HTTP Request, Google Drive, Google Sheets
Data & Sheets

📄 Documentation: Notion Guide

Google Sheets, Google Drive, HTTP Request +2
Data & Sheets

Overview

Google Sheets, Google Drive, HTTP Request