AutomationFlowsEmail & Gmail › Issue Branded Certificate Pdfs From Google Sheets with Templatefox and Gmail

Issue Branded Certificate Pdfs From Google Sheets with Templatefox and Gmail

ByVince V @templatefox on n8n.io

This workflow turns a Google Sheet into an automated certificate-issuing pipeline. The moment a new completion row is added — whether by your training team, a Zap, or a quiz platform — a branded PDF/A-2b (archival-grade) certificate is rendered by TemplateFox, archived in Google…

Event trigger★★★★☆ complexity10 nodesGoogle Sheets TriggerN8N Nodes TemplatefoxHTTP RequestGoogle DriveGmailGoogle Sheets
Email & Gmail Trigger: Event Nodes: 10 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #15438 — we link there as the canonical source.

This workflow follows the Gmail → Google Drive 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": "hNNDtV2nc8aN0EBy",
  "name": "Google Sheets \u2192 Certificate PDF \u2192 Gmail + Google Drive",
  "tags": [],
  "nodes": [
    {
      "id": "c1000001-0000-4000-a000-000000000001",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        -128
      ],
      "parameters": {
        "width": 460,
        "height": 1100,
        "content": "### Google Sheets \u2192 Certificate PDF \u2192 Gmail + Google Drive\nIssue branded, archival-quality certificate PDFs the moment a new completion row lands in your Google Sheet. The PDF is archived in Drive and the **permanent Drive URL** is written back to the source sheet, giving you a full audit trail of who got their certificate and when.\n\n**Full tutorial:** [templatefox.com/n8n/automate-certificates](https://templatefox.com/n8n/automate-certificates)\n\n### How it works\n1. **Google Sheets Trigger** fires on every new completion row\n2. **TemplateFox** maps the row data to your certificate template fields and renders a branded **PDF/A-2b** (archival-grade) certificate\n3. The PDF is **downloaded** and **archived** to your Google Drive folder\n4. The certificate is **emailed** to the participant with the permanent Drive link\n5. The source row is **updated** with the Drive URL and issue timestamp\n\n### Setup\n- [ ] Create a Google Sheet with columns: `Participant Name`, `Email`, `Course`, `Completion Date`, `Instructor`\n- [ ] Add two more columns to be written back: `Certificate URL`, `Issued At`\n- [ ] Connect **Google Sheets** OAuth2 in the trigger and update nodes\n- [ ] Install the **TemplateFox** community node (`n8n-nodes-templatefox`)\n- [ ] Add your **TemplateFox** API key \u2014 [get one free](https://app.templatefox.com)\n- [ ] Select your certificate template in the TemplateFox node and map each field to the matching column from the trigger\n- [ ] Connect **Gmail** OAuth2\n- [ ] Connect **Google Drive** OAuth2 and set your archive folder ID\n\n### Customize\n- Set your organisation's logo, signatures, and constant fields **directly in the TemplateFox template editor** \u2014 no need to pass them through n8n\n- Swap PDF/A-2b for `pdf/a-3b` if your training body requires PDF/A-3 compliance\n- Add a Slack node after the Drive step to ping your training team\n- Add an `IF` node before TemplateFox to skip rows where `Score` is below your passing threshold\n- Replace the Sheets trigger with a **Schedule** trigger + a `Get Many Rows` step to issue certificates in nightly batches"
      },
      "typeVersion": 1
    },
    {
      "id": "c1000001-0000-4000-a000-000000000002",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 280,
        "height": 360,
        "content": "## 1. Watch the sheet\nFires whenever a new completion row is added to your Google Sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "c1000001-0000-4000-a000-000000000003",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        288,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 280,
        "height": 360,
        "content": "## 2. Generate\nMap the row data to your certificate template and render a PDF/A-2b."
      },
      "typeVersion": 1
    },
    {
      "id": "c1000001-0000-4000-a000-000000000004",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 1100,
        "height": 360,
        "content": "## 3. Deliver, archive & track\nDownload, archive in Drive, email the participant with the permanent link, then write the Drive URL back to the source sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "c1000001-0000-4000-a000-000000000010",
      "name": "New Completion Row",
      "type": "n8n-nodes-base.googleSheetsTrigger",
      "position": [
        32,
        32
      ],
      "parameters": {
        "event": "rowAdded",
        "options": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultName": ""
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c1000001-0000-4000-a000-000000000011",
      "name": "TemplateFox",
      "type": "n8n-nodes-templatefox.templateFox",
      "position": [
        320,
        32
      ],
      "parameters": {
        "options": {
          "filename": "=certificate-{{ $json.Email || 'participant' }}",
          "pdfVariant": "pdf/a-2b"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c1000001-0000-4000-a000-000000000012",
      "name": "Download PDF",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        624,
        32
      ],
      "parameters": {
        "url": "={{ $json.url }}",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c1000001-0000-4000-a000-000000000013",
      "name": "Archive to Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        880,
        32
      ],
      "parameters": {
        "name": "=certificate-{{ $('New Completion Row').first().json.Email || 'participant' }}.pdf",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {
          "simplifyOutput": false
        },
        "folderId": ""
      },
      "typeVersion": 3
    },
    {
      "id": "c1000001-0000-4000-a000-000000000014",
      "name": "Email Certificate",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1152,
        32
      ],
      "parameters": {
        "sendTo": "={{ $('New Completion Row').first().json.Email }}",
        "message": "=<p>Hi {{ $('New Completion Row').first().json['Participant Name'] }},</p>\n<p>Congratulations on completing <strong>{{ $('New Completion Row').first().json.Course }}</strong>! Your official certificate is ready.</p>\n<p><a href=\"{{ $json.webViewLink }}\" style=\"display:inline-block;padding:12px 20px;background:#111;color:#fff;text-decoration:none;border-radius:6px;font-weight:600\">Download your certificate (PDF)</a></p>\n<p style=\"color:#555\">\n  <strong>Course:</strong> {{ $('New Completion Row').first().json.Course }}<br>\n  <strong>Completed:</strong> {{ $('New Completion Row').first().json['Completion Date'] }}\n</p>\n<p>Thanks for learning with us!</p>",
        "options": {},
        "subject": "=\ud83c\udf93 Your certificate for {{ $('New Completion Row').first().json.Course }}"
      },
      "typeVersion": 2.1
    },
    {
      "id": "c1000001-0000-4000-a000-000000000015",
      "name": "Update Sheet Row",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1408,
        32
      ],
      "parameters": {
        "columns": {
          "value": {
            "Email": "={{ $('New Completion Row').first().json.Email }}",
            "Issued At": "={{ $now.toISO() }}",
            "Certificate URL": "={{ $('Archive to Google Drive').first().json.webViewLink }}"
          },
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Email"
          ]
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('New Completion Row').first().json._sheet_name || '' }}"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('New Completion Row').first().json._sheet_id || '' }}"
        }
      },
      "typeVersion": 4.5
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "9d3e4586-0ba1-4da0-ad29-cd654d7eecab",
  "connections": {
    "TemplateFox": {
      "main": [
        [
          {
            "node": "Download PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download PDF": {
      "main": [
        [
          {
            "node": "Archive to Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email Certificate": {
      "main": [
        [
          {
            "node": "Update Sheet Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Completion Row": {
      "main": [
        [
          {
            "node": "TemplateFox",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Archive to Google Drive": {
      "main": [
        [
          {
            "node": "Email Certificate",
            "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

This workflow turns a Google Sheet into an automated certificate-issuing pipeline. The moment a new completion row is added — whether by your training team, a Zap, or a quiz platform — a branded PDF/A-2b (archival-grade) certificate is rendered by TemplateFox, archived in Google…

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

More Email & Gmail workflows → · Browse all categories →

Related workflows

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

Email & Gmail

This workflow watches Google Sheets for new rows, renders a personalized video with iLoveVideoEditor using the row data, uploads the finished MP4 to Google Drive, writes the Drive link back to the sam

Google Sheets Trigger, N8N Nodes Ilovevideoeditor, HTTP Request +3
Email & Gmail

Hiring teams often struggle with document follow-ups, offer letter generation, and stakeholder communication. Manual checks, email back-and-forth, and missing files slow down hiring and create chaos d

Google Sheets Trigger, HTTP Request, Slack +3
Email & Gmail

This workflow automates the end-to-end process of generating and sending client payment links using Google Sheets and Stripe.

Google Sheets Trigger, Gmail, HTTP Request +2
Email & Gmail

This template is ideal for HR teams, startup founders, operations leads, remote-first companies, and freelancers managing onboarding manually or across multiple tools.

Google Sheets Trigger, Jira, HubSpot Trigger +7
Email & Gmail

This workflow ingests proof-of-delivery and completion documents from Gmail or a webhook, extracts key fields with an OpenRouter vision model, reconciles them against Google Sheets dispatch data, arch

Gmail Trigger, HTTP Request, Google Sheets +2