AutomationFlowsWeb Scraping › Workshop Certificate Generator with Google Drive, Gmail & Qr Verification

Workshop Certificate Generator with Google Drive, Gmail & Qr Verification

ByJitesh Dugar @jiteshdugar on n8n.io

This workflow automates the entire pre-issuance process of workshop participation certificates. When an attendee submits a registration form via a webhook, the workflow validates the data, verifies the attendee’s email, generates a unique Certificate ID and QR code, creates a…

Webhook trigger★★★★☆ complexity22 nodesGoogle DriveGmailGoogle SheetsSlackN8N Nodes VerifiemailN8N Nodes HtmlcsstoimageHTTP Request
Web Scraping Trigger: Webhook Nodes: 22 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #10979 — 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": "",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "Workshop Certificate Automation - Pre-Issued",
  "tags": [
    {
      "id": "7sNS36mbSlImXupN",
      "name": "Certificate Generation",
      "createdAt": "2025-11-14T05:55:11.975Z",
      "updatedAt": "2025-11-14T05:55:11.975Z"
    },
    {
      "id": "AeHLbtZDeaqUsYfG",
      "name": "Workshop Automation",
      "createdAt": "2025-11-14T05:55:11.969Z",
      "updatedAt": "2025-11-14T05:55:11.969Z"
    },
    {
      "id": "SpTckBFiSBzzEm9W",
      "name": "Email Automation",
      "createdAt": "2025-10-24T17:28:28.418Z",
      "updatedAt": "2025-10-24T17:28:28.418Z"
    }
  ],
  "nodes": [
    {
      "id": "a2586676-cca1-4676-ad90-6f3243da7088",
      "name": "Webhook Registration",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1776,
        544
      ],
      "parameters": {
        "path": "workshop-registration",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "0d746971-e056-44b2-bd10-b8823792a053",
      "name": "Validate Required Fields",
      "type": "n8n-nodes-base.if",
      "position": [
        -1568,
        544
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1f6cd46d-fd80-4fd7-8190-0f2941d44636",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.body.name }}",
              "rightValue": ""
            },
            {
              "id": "21eae0c6-dad4-47e9-a456-8f3616dc7440",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.body.email }}",
              "rightValue": ""
            },
            {
              "id": "1fb586bf-deca-45b4-89a6-b20c7a9f9d16",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.body.event }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "9380542c-e324-4f7d-a0e3-2e78cefe7966",
      "name": "Check Email Valid",
      "type": "n8n-nodes-base.if",
      "position": [
        -1216,
        528
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f758a837-7f47-43f0-89bf-dd8609e1a045",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.valid }}",
              "rightValue": "deliverable"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "890bcef3-ed4e-4431-a25a-75ace96edbc4",
      "name": "Generate Certificate ID & QR",
      "type": "n8n-nodes-base.code",
      "position": [
        -928,
        352
      ],
      "parameters": {
        "jsCode": "// Generate unique certificate ID and QR code\nconst items = $input.all();\n\nreturn items.map(item => {\n  // Generate unique certificate ID\n  const timestamp = Date.now();\n  const randomStr = Math.random().toString(36).substr(2, 9).toUpperCase();\n  const certId = `CERT-${timestamp}-${randomStr}`;\n  \n  // Create verification URL\n  const verifyUrl = `https://workshopverify.com/cert?id=${certId}`;\n  \n  // Generate QR code URL using free API\n  const qrCodeUrl = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(verifyUrl)}`;\n  \n  // Format date for display\n  const formattedDate = new Date().toLocaleDateString('en-US', {\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric'\n  });\n  \n  return {\n    json: {\n      ...item.json,\n      certificateId: certId,\n      verifyUrl: verifyUrl,\n      qrCodeUrl: qrCodeUrl,\n      timestamp: new Date().toISOString(),\n      formattedDate: formattedDate\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "27056e8f-f086-4e98-93b1-fde7682767cc",
      "name": "Prepare Certificate HTML",
      "type": "n8n-nodes-base.set",
      "position": [
        -688,
        352
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "certificate-html",
              "name": "certificateHtml",
              "type": "string",
              "value": "=<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;700&display=swap');\n    \n    * {\n      margin: 0;\n      padding: 0;\n      box-sizing: border-box;\n    }\n    \n    body {\n      font-family: 'Poppins', sans-serif;\n      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      min-height: 100vh;\n      padding: 20px;\n    }\n    \n    .certificate {\n      width: 100%;\n      max-width: 900px;\n      background: white;\n      padding: 60px;\n      border-radius: 20px;\n      box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n      position: relative;\n      overflow: hidden;\n    }\n    \n    .certificate::before {\n      content: '';\n      position: absolute;\n      top: 0;\n      left: 0;\n      right: 0;\n      height: 10px;\n      background: linear-gradient(90deg, #667eea, #764ba2);\n    }\n    \n    .certificate::after {\n      content: '';\n      position: absolute;\n      bottom: 0;\n      left: 0;\n      right: 0;\n      height: 10px;\n      background: linear-gradient(90deg, #764ba2, #667eea);\n    }\n    \n    .header {\n      text-align: center;\n      margin-bottom: 40px;\n    }\n    \n    .logo {\n      font-size: 28px;\n      font-weight: 700;\n      color: #764ba2;\n      margin-bottom: 20px;\n    }\n    \n    h1 {\n      color: #333;\n      font-size: 42px;\n      font-weight: 700;\n      text-transform: uppercase;\n      letter-spacing: 3px;\n      margin: 20px 0;\n    }\n    \n    .subtitle {\n      color: #666;\n      font-size: 20px;\n      font-weight: 300;\n      margin: 20px 0;\n    }\n    \n    .recipient {\n      text-align: center;\n      margin: 50px 0;\n    }\n    \n    .recipient-name {\n      font-size: 48px;\n      color: #764ba2;\n      font-weight: 700;\n      margin: 20px 0;\n      text-transform: capitalize;\n      position: relative;\n      display: inline-block;\n    }\n    \n    .recipient-name::after {\n      content: '';\n      position: absolute;\n      bottom: -10px;\n      left: 0;\n      right: 0;\n      height: 3px;\n      background: linear-gradient(90deg, transparent, #764ba2, transparent);\n    }\n    \n    .designation {\n      font-size: 18px;\n      color: #666;\n      font-style: italic;\n      margin-top: 10px;\n    }\n    \n    .event-details {\n      background: linear-gradient(135deg, #f6f8fb 0%, #e9ecef 100%);\n      padding: 40px;\n      border-radius: 15px;\n      margin: 40px 0;\n      border: 2px solid #e0e0e0;\n    }\n    \n    .event-name {\n      font-size: 32px;\n      color: #333;\n      font-weight: 600;\n      margin: 15px 0;\n      text-align: center;\n    }\n    \n    .event-info {\n      display: flex;\n      justify-content: space-around;\n      margin-top: 30px;\n      flex-wrap: wrap;\n    }\n    \n    .info-item {\n      text-align: center;\n      margin: 10px;\n    }\n    \n    .info-icon {\n      font-size: 24px;\n      margin-bottom: 5px;\n    }\n    \n    .info-label {\n      font-size: 14px;\n      color: #999;\n      text-transform: uppercase;\n      letter-spacing: 1px;\n      margin-bottom: 5px;\n    }\n    \n    .info-value {\n      font-size: 16px;\n      color: #333;\n      font-weight: 500;\n    }\n    \n    .footer {\n      display: flex;\n      justify-content: space-between;\n      align-items: flex-end;\n      margin-top: 60px;\n      padding-top: 40px;\n      border-top: 2px solid #f0f0f0;\n    }\n    \n    .qr-section {\n      text-align: center;\n    }\n    \n    .qr-label {\n      font-size: 12px;\n      color: #999;\n      margin-bottom: 10px;\n      text-transform: uppercase;\n      letter-spacing: 1px;\n    }\n    \n    .qr-code {\n      width: 120px;\n      height: 120px;\n      padding: 10px;\n      background: white;\n      border: 2px solid #e0e0e0;\n      border-radius: 10px;\n    }\n    \n    .cert-id {\n      font-size: 11px;\n      color: #999;\n      margin-top: 10px;\n      font-family: 'Courier New', monospace;\n    }\n    \n    .signature-section {\n      text-align: center;\n    }\n    \n    .signature-line {\n      width: 200px;\n      height: 1px;\n      background: #333;\n      margin: 50px auto 10px;\n    }\n    \n    .signature-name {\n      font-size: 16px;\n      color: #333;\n      font-weight: 500;\n    }\n    \n    .signature-title {\n      font-size: 14px;\n      color: #666;\n      margin-top: 5px;\n    }\n    \n    .badge {\n      position: absolute;\n      top: 30px;\n      right: 30px;\n      background: #28a745;\n      color: white;\n      padding: 8px 20px;\n      border-radius: 20px;\n      font-size: 12px;\n      font-weight: 600;\n      text-transform: uppercase;\n      letter-spacing: 1px;\n      box-shadow: 0 4px 10px rgba(40, 167, 69, 0.3);\n    }\n  </style>\n</head>\n<body>\n  <div class=\"certificate\">\n    <div class=\"badge\">Pre-Issued</div>\n    \n    <div class=\"header\">\n      <div class=\"logo\">{{ $('Webhook Registration').item.json.body.organization }}</div>\n      <h1>Certificate of Registration</h1>\n    </div>\n    \n    <p class=\"subtitle\" style=\"text-align: center;\">This certifies that</p>\n    \n    <div class=\"recipient\">\n      <div class=\"recipient-name\">{{ $('Webhook Registration').item.json.body.name }}</div>\n      <div class=\"designation\">{{ $('Webhook Registration').item.json.body.designation }}</div>\n    </div>\n    \n    <p class=\"subtitle\" style=\"text-align: center;\">has successfully registered for</p>\n    \n    <div class=\"event-details\">\n      <div class=\"event-name\">{{ $('Webhook Registration').item.json.body.event }}</div>\n      \n      <div class=\"event-info\">\n        <div class=\"info-item\">\n          <div class=\"info-icon\">\ud83d\udcc5</div>\n          <div class=\"info-label\">Date</div>\n          <div class=\"info-value\">{{ $('Webhook Registration').item.json.body.date }}</div>\n        </div>\n        \n        <div class=\"info-item\">\n          <div class=\"info-icon\">\ud83d\udd50</div>\n          <div class=\"info-label\">Time</div>\n          <div class=\"info-value\">{{ $('Webhook Registration').item.json.body.time }}</div>\n        </div>\n        \n        <div class=\"info-item\">\n          <div class=\"info-icon\">\ud83d\udccd</div>\n          <div class=\"info-label\">Venue</div>\n          <div class=\"info-value\">{{ $('Webhook Registration').item.json.body.venue }}</div>\n        </div>\n      </div>\n    </div>\n    \n    <div class=\"footer\">\n      <div class=\"qr-section\">\n        <div class=\"qr-label\">Scan to Verify</div>\n        <img src=\"{{ $json.qrCodeUrl }}\" class=\"qr-code\" alt=\"QR Code\">\n        <div class=\"cert-id\">{{ $json.certificateId }}</div>\n      </div>\n      \n      <div class=\"signature-section\">\n        <div class=\"signature-line\"></div>\n        <p class=\"signature-name\">Workshop Coordinator</p>\n        <p class=\"signature-title\">{{ $('Webhook Registration').item.json.body.organization }}</p>\n      </div>\n    </div>\n  </div>\n</body>\n</html>"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7c21fec7-59c3-43fb-990c-e7a0d492262c",
      "name": "Upload to Google Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -32,
        352
      ],
      "parameters": {
        "name": "={{ $('Webhook Registration').item.json.body.name }}_{{ $('Generate Certificate ID & QR').item.json.certificateId }}.png",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_DRIVE_NAME"
        },
        "options": {
          "appPropertiesUi": {
            "appPropertyValues": [
              {
                "key": "certificateId",
                "value": "={{ $('Generate Certificate ID & QR').item.json.certificateId }}"
              },
              {
                "key": "event",
                "value": "={{ $('Webhook Registration').item.json.body.event }}"
              },
              {
                "key": "attendee",
                "value": "={{ $('Webhook Registration').item.json.body.name }}"
              }
            ]
          }
        },
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root",
          "cachedResultName": "YOUR_GOOGLE_DRIVE_FOLDER_NAME"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "01a08ef3-6bf9-4c27-aa9f-061f82c0c4b8",
      "name": "Send Certificate Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        208,
        352
      ],
      "parameters": {
        "sendTo": "={{ $('Check Email Valid').item.json.email }}",
        "message": "=<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    body {\n      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n      line-height: 1.6;\n      color: #333;\n      max-width: 600px;\n      margin: 0 auto;\n      padding: 20px;\n    }\n    .header {\n      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n      color: white;\n      padding: 30px;\n      border-radius: 10px 10px 0 0;\n      text-align: center;\n    }\n    .content {\n      background: #f8f9fa;\n      padding: 30px;\n      border-radius: 0 0 10px 10px;\n    }\n    .event-box {\n      background: white;\n      padding: 20px;\n      border-radius: 8px;\n      margin: 20px 0;\n      border-left: 4px solid #764ba2;\n    }\n    .button {\n      display: inline-block;\n      background: #764ba2;\n      color: white;\n      padding: 12px 30px;\n      text-decoration: none;\n      border-radius: 5px;\n      margin: 20px 0;\n    }\n    .footer {\n      text-align: center;\n      color: #666;\n      font-size: 14px;\n      margin-top: 30px;\n      padding-top: 20px;\n      border-top: 1px solid #e0e0e0;\n    }\n    .info-row {\n      display: flex;\n      padding: 10px 0;\n      border-bottom: 1px solid #f0f0f0;\n    }\n    .info-label {\n      font-weight: bold;\n      width: 100px;\n      color: #666;\n    }\n    .info-value {\n      flex: 1;\n      color: #333;\n    }\n    .certificate-preview {\n      text-align: center;\n      margin: 30px 0;\n      padding: 20px;\n      background: white;\n      border-radius: 8px;\n      box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n    }\n    .qr-instruction {\n      background: #e8f4fd;\n      border: 1px solid #bee5eb;\n      padding: 15px;\n      border-radius: 5px;\n      margin: 20px 0;\n    }\n  </style>\n</head>\n<body>\n  <div class=\"header\">\n    <h1 style=\"margin: 0; font-size: 28px;\">\ud83c\udf89 Registration Confirmed!</h1>\n    <p style=\"margin: 10px 0 0 0; opacity: 0.95;\">Your spot is reserved</p>\n  </div>\n  \n  <div class=\"content\">\n    <p style=\"font-size: 18px; color: #333;\">Hello <strong>{{ $json.name }}</strong>!</p>\n    \n    <p>Thank you for registering for our upcoming workshop. We're excited to have you join us!</p>\n    \n    <div class=\"event-box\">\n      <h2 style=\"margin: 0 0 15px 0; color: #764ba2;\">{{ $('Webhook Registration').item.json.body.event }}</h2>\n      \n      <div class=\"info-row\">\n        <span class=\"info-label\">\ud83d\udcc5 Date:</span>\n        <span class=\"info-value\">{{ $('Webhook Registration').item.json.body.date }}</span>\n      </div>\n      \n      <div class=\"info-row\">\n        <span class=\"info-label\">\ud83d\udd50 Time:</span>\n        <span class=\"info-value\">{{ $('Webhook Registration').item.json.body.time }}</span>\n      </div>\n      \n      <div class=\"info-row\">\n        <span class=\"info-label\">\ud83d\udccd Venue:</span>\n        <span class=\"info-value\">{{ $('Webhook Registration').item.json.body.venue }}</span>\n      </div>\n      \n      <div class=\"info-row\" style=\"border: none;\">\n        <span class=\"info-label\">\ud83c\udfab ID:</span>\n        <span class=\"info-value\" style=\"font-family: monospace;\">{{ $('Generate Certificate ID & QR').item.json.certificateId }}</span>\n      </div>\n    </div>\n    \n    <div class=\"qr-instruction\">\n      <strong>\ud83d\udcf1 Quick Check-in Instructions:</strong>\n      <ul style=\"margin: 10px 0; padding-left: 20px;\">\n        <li>Your pre-issued certificate is attached to this email</li>\n        <li>Present the QR code at the venue for fast check-in</li>\n        <li>No need to print - showing on your phone works!</li>\n      </ul>\n    </div>\n    \n    <div class=\"certificate-preview\">\n      <h3 style=\"color: #764ba2; margin: 0 0 15px 0;\">Your Certificate</h3>\n      <img src=\"{{ $('HTML/CSS to Image').item.json.image_url }}\" alt=\"Certificate Preview\" style=\"max-width: 100%; height: auto; border-radius: 5px; box-shadow: 0 4px 15px rgba(0,0,0,0.1);\">\n      \n      <a href=\"{{ $('HTML/CSS to Image').item.json.image_url }}\" class=\"button\">Download Certificate</a>\n    </div>\n    \n    <div style=\"background: #fff3cd; border: 1px solid #ffc107; padding: 15px; border-radius: 5px; margin: 20px 0;\">\n      <strong>\u26a0\ufe0f Important Reminders:</strong>\n      <ul style=\"margin: 10px 0; padding-left: 20px;\">\n        <li>Please arrive 15 minutes before the scheduled time</li>\n        <li>Bring a valid ID for verification if needed</li>\n        <li>Check your email for any updates about the event</li>\n      </ul>\n    </div>\n    \n    <p><strong>Need Help?</strong></p>\n    <p>If you have any questions or need to make changes to your registration, please reply to this email or contact our support team.</p>\n    \n    <div class=\"footer\">\n      <p><strong>{{ $('Webhook Registration').item.json.body.organization }}</strong></p>\n      <p>This is an automated confirmation email. Please do not reply directly to this message.</p>\n      <p style=\"font-size: 12px; color: #999;\">Certificate ID:  {{ $('Generate Certificate ID & QR').item.json.certificateId }}| Generated: {{ $('Generate Certificate ID & QR').item.json.formattedDate }}</p>\n    </div>\n  </div>\n</body>\n</html>",
        "options": {},
        "subject": "=\u2705 Your Workshop Certificate - {{ $('Webhook Registration').item.json.body.event }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "6db9df06-df3a-4b5b-86eb-708e96f4f367",
      "name": "Log to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        480,
        352
      ],
      "parameters": {
        "columns": {
          "value": {
            "- Name": "={{ $('Webhook Registration').item.json.body.name }}",
            "- Email": "={{ $('Webhook Registration').item.json.body.email }}",
            "- Event": "={{ $('Webhook Registration').item.json.body.event }}",
            "- Venue": "={{ $('Webhook Registration').item.json.body.venue }}",
            "- Status": "Pre-Issued",
            "- Drive Link": "={{ $('Upload to Google Drive').item.json.webViewLink }}",
            "- Event Date": "={{ $('Webhook Registration').item.json.body.date }}",
            "- Event Time": "={{ $('Webhook Registration').item.json.body.time }}",
            "- Designation": "={{ $('Webhook Registration').item.json.body.designation }}",
            "- Organization": "={{ $('Webhook Registration').item.json.body.organization }}",
            "- Certificate ID": "={{ $('Generate Certificate ID & QR').item.json.certificateId }}",
            "- Certificate URL": "={{ $('HTML/CSS to Image').item.json.image_url }}",
            "- Registration Date": "={{ $now}}"
          },
          "schema": [
            {
              "id": "- Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Event",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Event",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Certificate ID",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Certificate ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Registration Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Registration Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Event Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Event Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Event Time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Event Time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Venue",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Venue",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Organization",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Organization",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Designation",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Designation",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Certificate URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Certificate URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "- Drive Link",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "- Drive Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_DOCUMENT_ID/edit#gid=0",
          "cachedResultName": "YOUR_GOOGLE_SHEET_SHEET_NAME"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_DOCUMENT_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_DOCUMENT_ID/edit?usp=drivesdk",
          "cachedResultName": "YOUR_GOOGLE_SHEET_DOCUMENT_NAME"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "2491e515-84f9-42db-be2c-bd67368bbeca",
      "name": "Notify Slack Channel",
      "type": "n8n-nodes-base.slack",
      "position": [
        656,
        352
      ],
      "parameters": {
        "text": "=\u2705 *New Workshop Registration*\n\n\ud83d\udc64 *Name:* {{ $('Webhook Registration').item.json.body.name }}\n\ud83d\udce7 *Email:* {{ $('Webhook Registration').item.json.body.email }}\n\ud83c\udfaf *Event:* {{ $('Webhook Registration').item.json.body.event }}\n\ud83d\udcc5 *Date:* {{ $('Webhook Registration').item.json.body.date }} at {{ $('Webhook Registration').item.json.body.time }}\n\ud83d\udccd *Venue:* {{ $('Webhook Registration').item.json.body.venue }}\n\ud83c\udfe2 *Organization:* {{ $('Webhook Registration').item.json.body.organization }}\n\ud83d\udcbc *Designation:* {{ $('Webhook Registration').item.json.body.designation }}\n\n\ud83c\udfab *Certificate ID:* `{{ $('Generate Certificate ID & QR').item.json.certificateId }}`\n\ud83d\udd17 *Verify URL:* {{ $('Generate Certificate ID & QR').item.json.verifyUrl }}\n\n\ud83d\udcc4 *Certificate:* [View Certificate]({{ $('HTML/CSS to Image').item.json.image_url }})\n\ud83d\udcbe *Drive:* [View in Drive]({{ $('Upload to Google Drive').item.json.webViewLink }})",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_CHANNEL_ID",
          "cachedResultName": "YOUR_SLACK_CHANNEL_NAME"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f451dfce-f51d-487e-9144-f6e86623ddfb",
      "name": "Success Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        848,
        352
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"success\": true,\n  \"message\": \"Registration successful! Certificate sent to your email.\",\n  \"certificateId\": \"{{ $json.certificateId }}\",\n  \"verifyUrl\": \"{{ $json.verifyUrl }}\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "7d616ee2-887d-4b35-930c-5ba1204bf56a",
      "name": "Validation Error Response",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -1376,
        704
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"success\": false,\n  \"error\": \"Missing required fields\",\n  \"message\": \"Please provide name, email, and event information.\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "f31f8470-0746-4f88-aa9c-4da6a56c8dfb",
      "name": "Email Verification Error",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -912,
        640
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"success\": false,\n  \"error\": \"Invalid email address\",\n  \"message\": \"The provided email address could not be verified. Please check and try again.\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "d50f4202-32b0-43f1-80af-a40dbf6d012d",
      "name": "Verifi Email",
      "type": "n8n-nodes-verifiemail.verifiEmail",
      "position": [
        -1376,
        528
      ],
      "parameters": {
        "email": "={{ $json.body.email }}"
      },
      "credentials": {
        "verifiEmailApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5487d115-1006-4681-b552-534ce4ba8830",
      "name": "HTML/CSS to Image",
      "type": "n8n-nodes-htmlcsstoimage.htmlCssToImage",
      "position": [
        -512,
        352
      ],
      "parameters": {
        "html_content": "={{ $json.certificateHtml }}"
      },
      "credentials": {
        "htmlcsstoimgApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "47674dfd-22ce-4b74-9a48-d7b5bd95e04c",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1824,
        -16
      ],
      "parameters": {
        "width": 528,
        "height": 400,
        "content": "## How it Works\nThis workflow automates issuing pre-registration workshop certificates. When a participant submits the registration form via webhook, their data is validated and their email is checked using VerifiEmail. If valid, the workflow generates a unique certificate ID, builds a verification URL and QR code, converts the certificate HTML into an image, saves it to Google Drive, emails it to the attendee, logs the registration in Google Sheets, and sends a Slack notification to the organizers. A JSON confirmation is also returned to the webhook.\n\n## Setup Steps\n1. Add required credentials: VerifiEmail, HTMLCSStoImage, Gmail, Google Sheets, Google Drive, Slack.  \n2. Replace placeholder URLs or Drive folders with your own.  \n3. Update certificate HTML template with your branding (optional).  \n4. Publish the workflow and connect your form to the webhook URL.  \n5. Test using a real email address.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "136c210a-18d9-4b7a-a43c-e351b4a98283",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1824,
        416
      ],
      "parameters": {
        "color": 7,
        "width": 752,
        "height": 256,
        "content": "## Validation\nWebhook receives form data.  \nNode checks if name, email, and event are present.  \nIf missing \u2192 return validation error.  \nEmail is then verified using VerifiEmail.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "3c74feda-8878-492a-a004-4d6137216a7d",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -992,
        256
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 256,
        "content": "## Certificate Generation\nGenerates unique Certificate ID + QR code, inserts attendee/event details into the HTML template, and converts it into PNG using HTMLCSStoImage.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b3d70d79-c91f-4752-8103-eec93843ae22",
      "name": "Download Binary File",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -304,
        352
      ],
      "parameters": {
        "url": "={{ $json.image_url }}",
        "options": {}
      },
      "typeVersion": 4.3
    },
    {
      "id": "ec8095fb-8c53-4a7f-b8f2-e86ca70db8e1",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -336,
        240
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 256,
        "content": "## Storage\nCertificate PNG is downloaded and uploaded to Google Drive.  \nMetadata (event, certificate ID, attendee) is saved for easy lookup.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ec7cf677-a693-4a2f-91d5-686ddd672148",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        128,
        240
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 272,
        "content": "## Email Delivery\nSends participant an HTML email including event info, QR code, and the certificate image/download link.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c6c05e22-62c7-439d-bc16-58d8d2858439",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        432,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 352,
        "height": 320,
        "content": "## Logging & Alerts\nRegistration + certificate details are logged in Google Sheets.  \nSlack message notifies organizers of new registration.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "50eabd16-52a2-4610-8aa9-c6f70796a7a9",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        816,
        256
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 224,
        "content": "## Response\nReturns JSON with success message, certificateId, and verification URL.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "Verifi Email": {
      "main": [
        [
          {
            "node": "Check Email Valid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Email Valid": {
      "main": [
        [
          {
            "node": "Generate Certificate ID & QR",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email Verification Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTML/CSS to Image": {
      "main": [
        [
          {
            "node": "Download Binary File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download Binary File": {
      "main": [
        [
          {
            "node": "Upload to Google Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Google Sheets": {
      "main": [
        [
          {
            "node": "Notify Slack Channel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Slack Channel": {
      "main": [
        [
          {
            "node": "Success Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Registration": {
      "main": [
        [
          {
            "node": "Validate Required Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Certificate Email": {
      "main": [
        [
          {
            "node": "Log to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to Google Drive": {
      "main": [
        [
          {
            "node": "Send Certificate Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Certificate HTML": {
      "main": [
        [
          {
            "node": "HTML/CSS to Image",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Required Fields": {
      "main": [
        [
          {
            "node": "Verifi Email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Validation Error Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Certificate ID & QR": {
      "main": [
        [
          {
            "node": "Prepare Certificate HTML",
            "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.

Pro

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

About this workflow

This workflow automates the entire pre-issuance process of workshop participation certificates. When an attendee submits a registration form via a webhook, the workflow validates the data, verifies the attendee’s email, generates a unique Certificate ID and QR code, creates a…

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

More Web Scraping workflows → · Browse all categories →

Related workflows

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

Web Scraping

Automated Email Verification & Digital Health Card Generator

HTTP Request, Google Drive, Gmail +5
Web Scraping

Verified Corporate Training Certificate with CEUs – Fully Automated & Verifiable

Google Drive, Slack, Google Sheets +4
Web Scraping

This comprehensive workflow automates the entire testimonial collection and publishing process, from submission to social media-ready content. It uses AI to enhance testimonials, generates beautiful b

OpenAI, N8N Nodes Htmlcsstoimage, HTTP Request +3
Web Scraping

Simplify employee performance reviews with AI-powered automation. This workflow transforms raw feedback and evaluation inputs into clear, structured, and professional performance review summaries — sa

OpenAI, Gmail, HTTP Request +3
Web Scraping

A comprehensive n8n workflow template that completely automates the startup pitch deck submission process for accelerators, incubators, VC firms, and startup competitions. This workflow validates foun

Google Drive, Gmail, N8N Nodes Verifiemail +2