証明書ジェネレーター
上級
これはContent Creation, Multimodal AI分野の自動化ワークフローで、25個のノードを含みます。主にIf, Code, Gmail, Slack, Webhookなどのノードを使用。 VerifiEmailとHTMLcsstoImgを使用して証明書を生成し、Gmail経由で送信
前提条件
- •Googleアカウント + Gmail API認証情報
- •Slack Bot Token または Webhook URL
- •HTTP Webhookエンドポイント(n8nが自動生成)
- •Google Sheets API認証情報
使用ノード (25)
ワークフロープレビュー
ノード接続関係を可視化、ズームとパンをサポート
ワークフローをエクスポート
以下のJSON設定をn8nにインポートして、このワークフローを使用できます
{
"id": "",
"meta": {
"instanceId": ""
},
"name": "certificate generator",
"tags": [
{
"id": "CWzMtsCN0QfPR9PC",
"name": "certificates",
"createdAt": "2025-10-04T15:28:20.021Z",
"updatedAt": "2025-10-04T15:28:20.021Z"
},
{
"id": "qFR253LK8bI8GX4z",
"name": "automation",
"createdAt": "2025-10-04T15:28:20.027Z",
"updatedAt": "2025-10-04T15:28:20.027Z"
}
],
"nodes": [
{
"id": "8aef6c7c-9dfd-483b-9b66-ee9a21ad0e3b",
"name": "資格情報設定ガイド",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3024,
-96
],
"parameters": {
"color": 7,
"width": 452,
"height": 856,
"content": "## 🔧 CREDENTIALS SETUP REQUIRED\n\nBefore activating this workflow, configure these credentials:\n\n1. VerifiEmail API\n - Sign up at https://verifi.email\n - Get your API key from dashboard\n - In n8n: Add VerifiEmail credential\n - Paste API key\n\n2. HTMLcsstoImage API\n - Sign up at https://htmlcsstoimg.com\n - Get User ID and API Key\n - In n8n: Add HTMLcsstoImg credential\n - Enter User ID and API Key\n\n3. Gmail OAuth2 (for sending emails)\n - Go to Settings > Credentials\n - Add Gmail OAuth2\n - Follow Google OAuth setup\n - Grant necessary permissions\n - Test connection\n\n4. Google Sheets OAuth2 (for logging)\n - Add Google Sheets OAuth2 credential\n - Create spreadsheet: \"Certificates Log\"\n - Add these column headers:\n • Certificate ID\n • Recipient Name\n • Course\n • Email\n • Completion Date\n • Generated At\n • Certificate URL\n • Status\n • Instructor\n • Duration\n\n✅ All credentials configured in this workflow"
},
"typeVersion": 1
},
{
"id": "713712a6-27e5-482b-8994-eae001ab2785",
"name": "Webhook 情報",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2512,
64
],
"parameters": {
"color": 7,
"width": 444,
"height": 628,
"content": "## 📥 WEBHOOK TRIGGER\n\nAccepts POST requests with certificate data\n\nRequired JSON format:\n```\n{\n \"name\": \"John Doe\",\n \"course\": \"Course Name\",\n \"date\": \"2025-10-04\",\n \"email\": \"user@example.com\"\n}\n```\nOptional fields:\n```\n{\n \"instructor\": \"Jane Smith\",\n \"duration\": \"40 hours\",\n \"certificateId\": \"CERT-2025-001\"\n}\n```\n🔗 Your Webhook URL:\n```https://n8n.exildraw.com/webhook-test/certificate-generator```\n\n📝 All data is accessed via:\n{{ $json.body.fieldName }}"
},
"typeVersion": 1
},
{
"id": "a8b8e036-c01d-4091-b817-43611a1e2643",
"name": "証明書リクエスト Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-2192,
544
],
"webhookId": "certificate-generator",
"parameters": {
"path": "certificate-generator",
"options": {},
"httpMethod": "POST",
"responseMode": "lastNode"
},
"typeVersion": 2
},
{
"id": "3129040e-f390-4661-b17a-32b5c029cd8b",
"name": "メール検証情報",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2016,
144
],
"parameters": {
"color": 7,
"width": 380,
"height": 548,
"content": "## 📧 EMAIL VALIDATION STEP\n\nUses VerifiEmail API to validate recipient email\n\nChecks performed:\n✓ RFC Compliance (proper email format)\n✓ Valid MX Records (domain accepts email)\n✓ Spoof Detection (checks for fake domains)\n✓ Disposable Email Detection (blocks temp emails)\n\nOutput includes:\n• valid: true/false\n• provider: email service provider\n• MX records: mail server details\n\n⚠️ Credential Required: VerifiEmail API key\n\nNext Step: IF node validates this + other fields"
},
"typeVersion": 1
},
{
"id": "5c1071ea-cc45-49b2-9498-083d3a09508b",
"name": "検証ロジック",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1584,
80
],
"parameters": {
"color": 7,
"width": 360,
"height": 596,
"content": "## ✅ VALIDATION CHECKPOINT\n\nChecks ALL required conditions:\n\nFrom Webhook:\n1. Name is not empty\n2. Course is not empty\n3. Date is not empty\n\nFrom VerifiEmail:\n4. Email validation = true\n\nAll conditions must pass (AND logic)\n\n✓ TRUE → Continue to Combine Data\n✗ FALSE → Stop workflow with error\n\nAccessing data:\n• Webhook: $('Certificate Request Webhook').item.json.body.field\n• Email: $json.valid"
},
"typeVersion": 1
},
{
"id": "745c8af8-c38e-4257-968d-c8abeb30e5d3",
"name": "データ結合情報",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1184,
-32
],
"parameters": {
"color": 7,
"width": 380,
"height": 716,
"content": "## 🔄 COMBINE WEBHOOK + EMAIL DATA\n\nMerges certificate data with email validation results\n\nInput sources:\n• Webhook data: name, course, date, email, instructor, duration\n• Email validation: valid, provider, MX records\n\nOutput structure:\n```\n{\n name, course, date, email,\n instructor, duration, certificateId,\n emailValidation: {\n valid, provider, rfcCompliant,\n validMxRecord, disposable\n }\n}\n```\nPurpose: Creates clean data structure for HTML generation\n\n⚡ Auto-generates certificateId if not provided\n📅 Keeps original date format for later formatting"
},
"typeVersion": 1
},
{
"id": "99566da7-4b33-4df0-a280-5a5db861bf13",
"name": "HTML生成情報",
"type": "n8n-nodes-base.stickyNote",
"position": [
-768,
-48
],
"parameters": {
"color": 7,
"width": 380,
"height": 724,
"content": "## 🎨 HTML CERTIFICATE GENERATOR\n\nCreates beautiful HTML certificate with:\n\nDesign Features:\n• Purple gradient background (#667eea → #764ba2)\n• Professional typography (Playfair Display + Montserrat)\n• Gold achievement badge with star\n• Clean white certificate with borders\n• Signature section with instructor name\n• Formatted completion date\n\nDynamic Content:\n• Recipient name (large, centered)\n• Course name\n• Completion date (formatted as \"Month Day, Year\")\n• Certificate ID (bottom right)\n• Instructor name (or \"Program Director\" if not provided)\n• Duration (optional, shown if provided)\n\nAuto-generates:\n• Unique Certificate ID if not provided\n• Format: CERT-{timestamp}-{random}\n\nOutput: Complete HTML ready for image conversion"
},
"typeVersion": 1
},
{
"id": "d2f582b7-9d23-43b9-bc05-e50f96ad122f",
"name": "HTML証明書を生成",
"type": "n8n-nodes-base.code",
"position": [
-640,
528
],
"parameters": {
"jsCode": "// Certificate HTML Generator\nconst items = $input.all();\n\nreturn items.map(item => {\n const data = item.json;\n \n // Generate unique certificate ID if not provided\n const certId = data.certificateId || `CERT-${Date.now()}-${Math.random().toString(36).substr(2, 9).toUpperCase()}`;\n \n // Format date nicely\n const certDate = new Date(data.date).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric'\n });\n \n // HTML Template with inline CSS\n const htmlContent = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Certificate of Completion</title>\n <style>\n @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Montserrat:wght@300;400;600&display=swap');\n \n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n \n body {\n width: 1200px;\n height: 850px;\n font-family: 'Montserrat', sans-serif;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 40px;\n }\n \n .certificate {\n background: white;\n width: 100%;\n height: 100%;\n border: 20px solid #f8f9fa;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n position: relative;\n padding: 60px 80px;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n }\n \n .certificate::before {\n content: '';\n position: absolute;\n top: 35px;\n left: 35px;\n right: 35px;\n bottom: 35px;\n border: 3px solid #667eea;\n pointer-events: none;\n }\n \n .header {\n text-align: center;\n margin-bottom: 20px;\n }\n \n .logo {\n width: 80px;\n height: 80px;\n margin: 0 auto 15px;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n font-size: 36px;\n font-weight: bold;\n }\n \n .title {\n font-family: 'Playfair Display', serif;\n font-size: 48px;\n font-weight: 700;\n color: #2d3748;\n letter-spacing: 2px;\n margin-bottom: 10px;\n }\n \n .subtitle {\n font-size: 18px;\n color: #718096;\n text-transform: uppercase;\n letter-spacing: 3px;\n font-weight: 300;\n }\n \n .content {\n text-align: center;\n flex-grow: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n }\n \n .presented-to {\n font-size: 16px;\n color: #718096;\n text-transform: uppercase;\n letter-spacing: 2px;\n margin-bottom: 20px;\n }\n \n .recipient-name {\n font-family: 'Playfair Display', serif;\n font-size: 56px;\n font-weight: 700;\n color: #667eea;\n margin-bottom: 30px;\n padding-bottom: 15px;\n border-bottom: 3px solid #e2e8f0;\n display: inline-block;\n min-width: 500px;\n }\n \n .description {\n font-size: 18px;\n color: #4a5568;\n line-height: 1.8;\n margin-bottom: 25px;\n max-width: 700px;\n margin-left: auto;\n margin-right: auto;\n }\n \n .course-name {\n font-weight: 600;\n color: #2d3748;\n font-size: 24px;\n margin: 20px 0;\n }\n \n .footer {\n display: flex;\n justify-content: space-between;\n align-items: flex-end;\n margin-top: 40px;\n }\n \n .signature-block {\n text-align: center;\n flex: 1;\n }\n \n .signature-line {\n border-top: 2px solid #2d3748;\n width: 250px;\n margin: 0 auto 10px;\n padding-top: 5px;\n }\n \n .signature-name {\n font-weight: 600;\n color: #2d3748;\n font-size: 16px;\n margin-bottom: 5px;\n }\n \n .signature-title {\n font-size: 14px;\n color: #718096;\n }\n \n .date-block {\n text-align: center;\n }\n \n .date-label {\n font-size: 12px;\n color: #718096;\n text-transform: uppercase;\n letter-spacing: 1px;\n margin-bottom: 5px;\n }\n \n .date-value {\n font-weight: 600;\n color: #2d3748;\n font-size: 16px;\n }\n \n .cert-id {\n position: absolute;\n bottom: 15px;\n right: 25px;\n font-size: 10px;\n color: #a0aec0;\n letter-spacing: 1px;\n }\n \n .badge {\n position: absolute;\n top: 50px;\n right: 60px;\n width: 100px;\n height: 100px;\n background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 15px rgba(255, 215, 0, 0.4);\n }\n \n .badge::before {\n content: '★';\n font-size: 50px;\n color: white;\n }\n </style>\n</head>\n<body>\n <div class=\"certificate\">\n <div class=\"badge\"></div>\n \n <div class=\"header\">\n <div class=\"logo\">C</div>\n <h1 class=\"title\">Certificate of Completion</h1>\n <p class=\"subtitle\">This certifies that</p>\n </div>\n \n <div class=\"content\">\n <div class=\"recipient-name\">${data.name}</div>\n \n <p class=\"description\">\n has successfully completed the course\n </p>\n \n <div class=\"course-name\">${data.course}</div>\n \n ${data.duration ? `<p class=\"description\" style=\"margin-top: 10px; font-size: 16px;\">Duration: ${data.duration}</p>` : ''}\n </div>\n \n <div class=\"footer\">\n <div class=\"signature-block\">\n <div class=\"signature-line\"></div>\n <div class=\"signature-name\">${data.instructor || 'Program Director'}</div>\n <div class=\"signature-title\">Instructor</div>\n </div>\n \n <div class=\"date-block\">\n <div class=\"date-label\">Date of Completion</div>\n <div class=\"date-value\">${certDate}</div>\n </div>\n </div>\n \n <div class=\"cert-id\">Certificate ID: ${certId}</div>\n </div>\n</body>\n</html>\n `;\n \n return {\n json: {\n ...data,\n certificateId: certId,\n html: htmlContent,\n formattedDate: certDate\n }\n };\n});"
},
"typeVersion": 2
},
{
"id": "9e764afe-be0f-4a6a-b5fc-4e2213353ae4",
"name": "画像変換情報",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
-16
],
"parameters": {
"color": 7,
"width": 380,
"height": 704,
"content": "## IMAGE CONVERSION\n\nConverts HTML certificate to high-quality PNG image\n\nService: HTMLcsstoImg API\nAPI Endpoint: hcti.io\n\nConfiguration:\n• Input: {{ $json.html }}\n• Google Fonts: Playfair Display|Montserrat\n• Output: PNG image\n• Resolution: 1200x850px\n\nAPI Response:\n```\n{\n \"image_url\": \"https://hcti.io/v1/image/[id]\",\n \"image_id\": \"[unique-id]\"\n}\n```\n⚠️ Credential Required: HTMLcsstoImg API\n User ID + API Key configured\n\n✅ Direct shareable URL returned\n📥 Image hosted on HTMLcsstoImg servers\n🔗 Permanent URL (doesn't expire)"
},
"typeVersion": 1
},
{
"id": "edac6e11-432b-42f2-9128-b39d4585bd5b",
"name": "メール配信情報",
"type": "n8n-nodes-base.stickyNote",
"position": [
128,
-128
],
"parameters": {
"color": 7,
"width": 380,
"height": 808,
"content": "## CERTIFICATE EMAIL DELIVERY\n\nSends professional congratulatory email via Gmail\n\nEmail Contents:\n• Subject: \"🎓 Congratulations! Your Certificate of Completion\"\n• HTML-formatted message with:\n - Gradient header with recipient name\n - Course details in styled box\n - Download button with certificate URL\n - Certificate details table\n - Call-to-action to share on LinkedIn\n - Professional footer\n\nData Sources:\n• Recipient: From \"Code in JavaScript\" node\n• Certificate details: From \"Generate HTML Certificate\" node\n• Certificate URL: From \"HTML/CSS to Image\" node\n\nVariables used:\n• {{ $('Generate HTML Certificate').item.json.name }}\n• {{ $('Generate HTML Certificate').item.json.course }}\n• {{ $('Generate HTML Certificate').item.json.certificateId }}\n• {{ $json.image_url }}\n\n⚠️ Credential: Gmail OAuth2"
},
"typeVersion": 1
},
{
"id": "7acdd47b-7014-4e0f-8b44-5acf326412be",
"name": "証明書メールを送信",
"type": "n8n-nodes-base.gmail",
"position": [
288,
528
],
"webhookId": "",
"parameters": {
"sendTo": "={{ $('Code in JavaScript').item.json.email }}",
"message": "=<!DOCTYPE html>\n<html>\n<head>\n <style>\n body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; margin: 0; padding: 0; }\n .container { max-width: 600px; margin: 0 auto; }\n .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); \n color: white; padding: 40px 20px; text-align: center; }\n .header h1 { margin: 0; font-size: 28px; }\n .content { background: #f8f9fa; padding: 40px 30px; }\n .content p { margin: 15px 0; }\n .course-box { background: white; border-left: 4px solid #667eea; \n padding: 20px; margin: 25px 0; border-radius: 5px; }\n .course-box h2 { color: #667eea; margin: 0 0 10px 0; font-size: 22px; }\n .button { background: #667eea; color: white; padding: 15px 30px; \n text-decoration: none; border-radius: 5px; display: inline-block; \n margin: 20px 0; font-weight: bold; }\n .button:hover { background: #5568d3; }\n .details { background: white; padding: 20px; border-radius: 5px; margin: 20px 0; }\n .details ul { list-style: none; padding: 0; }\n .details li { padding: 8px 0; border-bottom: 1px solid #e2e8f0; }\n .details li:last-child { border-bottom: none; }\n .details strong { color: #667eea; }\n .footer { text-align: center; padding: 30px 20px; color: #718096; font-size: 14px; }\n .footer p { margin: 5px 0; }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"header\">\n <h1>🎉 Congratulations, {{ $('Generate HTML Certificate').item.json.name }} !</h1>\n <p style=\"margin: 10px 0 0 0; font-size: 16px;\">You've successfully completed your course</p>\n </div>\n \n <div class=\"content\">\n <p>We're thrilled to celebrate your achievement! You have successfully completed:</p>\n \n <div class=\"course-box\">\n <h2>{{ $('Generate HTML Certificate').item.json.course }}</h2>\n <p style=\"margin: 0; color: #718096;\">Completion Date: {{ $('Generate HTML Certificate').item.json.formattedDate }}</p>\n </div>\n \n <p>Your certificate is ready and available for download. Share your accomplishment with your professional network!</p>\n \n <div style=\"text-align: center;\">\n <a href=\"{{ $json.image_url }}\" class=\"button\">📥 Download Certificate</a>\n </div>\n \n <div class=\"details\">\n <p><strong>📋 Certificate Details:</strong></p>\n <ul>\n <li><strong>Certificate ID:</strong>{{ $('Generate HTML Certificate').item.json.certificateId }} </li>\n <li><strong>Recipient:</strong>{{ $('Generate HTML Certificate').item.json.name }} </li>\n <li><strong>Course:</strong> {{ $('Generate HTML Certificate').item.json.course }}</li>\n <li><strong>Completion Date:</strong> {{ $('Generate HTML Certificate').item.json.formattedDate }}</li>\n {{ $json.duration ? '<li><strong>Duration:</strong> ' + $json.duration + '</li>' : '' }}\n {{ $json.instructor ? '<li><strong>Instructor:</strong> ' + $json.instructor + '</li>' : '' }}\n </ul>\n </div>\n \n <p><strong>💼 Share Your Success:</strong></p>\n <p>Don't forget to add this certificate to your LinkedIn profile and share it with your network to showcase your new skills!</p>\n \n <p style=\"margin-top: 30px; color: #718096; font-size: 14px;\">If you have any questions about your certificate, please don't hesitate to reach out to our support team.</p>\n </div>\n \n <div class=\"footer\">\n <p><strong>Thank you for learning with us!</strong></p>\n <p>© 2025 Your Organization. All rights reserved.</p>\n <p style=\"font-size: 12px; margin-top: 15px;\">Certificate verification available at: yoursite.com/verify</p>\n </div>\n </div>\n</body>\n</html>",
"options": {},
"subject": "🎓 Congratulations! Your Certificate of Completion"
},
"credentials": {
"gmailOAuth2": {
"id": "",
"name": "Gmail OAuth2"
}
},
"typeVersion": 2.1
},
{
"id": "5820e8bb-2f26-4d04-8445-61ea99902d35",
"name": "データベースロギング情報",
"type": "n8n-nodes-base.stickyNote",
"position": [
592,
-176
],
"parameters": {
"color": 7,
"width": 380,
"height": 864,
"content": "## GOOGLE SHEETS LOGGING\n\nRecords every certificate to spreadsheet for tracking\n\nSpreadsheet: \"Certificates Log\"\nSheet: Sheet1\n\nLogged Data (10 columns):\n1. Certificate ID - Unique identifier\n2. Recipient Name - Full name\n3. Course - Course/program name\n4. Email - Recipient email\n5. Completion Date - Original date from webhook\n6. Generated At - Current timestamp (ISO format)\n7. Certificate URL - Direct image link\n8. Status - Always \"Sent\"\n9. Instructor - Instructor name\n10. Duration - Course duration\n\nData Sources:\n• Most fields: From \"Generate HTML Certificate\" node\n• Certificate URL: From \"HTML/CSS to Image\" node\n• Generated At: {{ $now.toISO() }}\n\nOperation: Append or Update Row\nMatch Column: Certificate ID (prevents duplicates)\n\n⚠️ Credential: Google Sheets OAuth2 \n\nPurpose: Audit trail, analytics, certificate verification"
},
"typeVersion": 1
},
{
"id": "37b407ee-9362-402a-b708-5c821e1e1116",
"name": "Google シートにログ記録",
"type": "n8n-nodes-base.googleSheets",
"position": [
752,
528
],
"parameters": {
"columns": {
"value": {
"Email": "={{ $('Generate HTML Certificate').item.json.email }}",
"Course": "={{ $('Generate HTML Certificate').item.json.course }}",
"Status": "Sent",
"Duration": "={{ $('Generate HTML Certificate').item.json.duration }}",
"Instructor": "={{ $('Generate HTML Certificate').item.json.instructor }}",
"Generated At": "={{ $now.toISO() }}",
"Certificate ID": "={{ $('Generate HTML Certificate').item.json.certificateId }}",
"Recipient Name": "={{ $('Generate HTML Certificate').item.json.name }}",
"Certificate URL": "={{ $('HTML/CSS to Image').item.json.image_url }}",
"Completion Date ": "={{ $('Generate HTML Certificate').item.json.date }}"
},
"schema": [
{
"id": "Certificate ID",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Certificate ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Recipient Name",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Recipient Name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Course",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Course",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Email",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Completion Date ",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Completion Date ",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Generated At",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Generated At",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Certificate URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Certificate URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Instructor",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Instructor",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Duration",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Duration",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"Certificate ID"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultUrl": "",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultUrl": "",
"cachedResultName": "Certificates Log"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "",
"name": "Google Sheets OAuth2"
}
},
"typeVersion": 4.4
},
{
"id": "559bc397-1e64-4f9e-91e0-69f01a2de564",
"name": "成功レスポンス情報",
"type": "n8n-nodes-base.stickyNote",
"position": [
1024,
352
],
"parameters": {
"color": 7,
"width": 716,
"height": 624,
"content": "## ⚠️ RECOMMENDED ADDITION\n\nMISSING: Success Response to Webhook\n\nCurrently, workflow completes but doesn't send response back to webhook caller.\n\nTo add:\n1. Add \"Respond to Webhook\" node\n After \"Log to Google Sheets\"\n\n2. Configure response:\n Response Code: 200\n Response Body:\n ```\n {\n \"success\": true,\n \"message\": \"Certificate generated successfully!\",\n \"certificateId\": \"{{ $('Generate HTML Certificate').item.json.certificateId }}\",\n \"recipientEmail\": \"{{ $('Generate HTML Certificate').item.json.email }}\",\n \"certificateUrl\": \"{{ $('HTML/CSS to Image').item.json.image_url }}\",\n \"generatedAt\": \"{{ $now.toISO() }}\"\n }\n ```\nWhy it's important:\n• API integrations need confirmation\n• Useful for tracking in external systems\n• Provides certificate URL to caller\n• Better for automation workflows\n\nWithout it: Workflow succeeds but caller gets no response"
},
"typeVersion": 1
},
{
"id": "bd541a23-e982-4b64-82e2-30aea3e7601d",
"name": "エラー処理情報",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2032,
1088
],
"parameters": {
"color": 7,
"width": 472,
"height": 564,
"content": "## ⚠️ ERROR HANDLING\n\nWorkflow includes error catching and notification\n\nError Trigger:\n• Catches any workflow errors\n• Activates separate error flow\n\nError Processing:\n1. Format Error Details (Code node)\n - Extracts error message\n - Identifies failed node\n - Captures user data (name, email, course)\n - Logs execution ID and timestamp\n\n2. Send Slack Alert (DISABLED)\n - Would notify admin team\n - Enable if you have Slack integration\n - Shows error details and user info\n\nNote: Slack alert currently disabled\nTo enable: Configure Slack credential and enable node\n\nMissing: Error response to webhook caller\nRecommendation: Add \"Respond to Webhook\" node after error trigger to return 500 status code"
},
"typeVersion": 1
},
{
"id": "429a6ac5-d269-4176-ac81-d65117df54dd",
"name": "ワークフローエラー時",
"type": "n8n-nodes-base.errorTrigger",
"position": [
-1680,
1216
],
"parameters": {},
"typeVersion": 1
},
{
"id": "e3cc736c-3a91-42d5-9037-5ffcad3e8cab",
"name": "エラー詳細をフォーマット",
"type": "n8n-nodes-base.code",
"position": [
-1472,
1216
],
"parameters": {
"jsCode": "// Extract error information\nconst errorData = $input.first().json;\n\nreturn [{\n json: {\n errorMessage: errorData.error?.message || 'Unknown error occurred',\n errorNode: errorData.node?.name || 'Unknown node',\n timestamp: new Date().toISOString(),\n workflowId: $workflow.id,\n workflowName: $workflow.name,\n executionId: $execution.id,\n userData: {\n name: errorData.json?.name || 'N/A',\n email: errorData.json?.email || 'N/A',\n course: errorData.json?.course || 'N/A'\n },\n fullError: JSON.stringify(errorData, null, 2)\n }\n}];"
},
"typeVersion": 2
},
{
"id": "c1ec5078-2bc7-4f7d-b413-fa0ca7691a15",
"name": "Slack アラートを送信",
"type": "n8n-nodes-base.slack",
"notes": "Optional: Enable if you want Slack notifications",
"disabled": true,
"position": [
-1280,
1216
],
"webhookId": "",
"parameters": {
"text": "=🚨 **Certificate Generation Failed**\n\n**Error:** {{ $json.errorMessage }}\n**Node:** {{ $json.errorNode }}\n**Time:** {{ $json.timestamp }}\n\n**User Details:**\n• Name: {{ $json.userData.name }}\n• Email: {{ $json.userData.email }}\n• Course: {{ $json.userData.course }}\n\n**Execution ID:** {{ $json.executionId }}\n**Workflow:** {{ $json.workflowName }}",
"select": "channel",
"channelId": {
"__rl": true,
"mode": "list",
"value": "C12345",
"cachedResultName": "alerts"
},
"otherOptions": {}
},
"typeVersion": 2.2
},
{
"id": "7d756f81-a0ac-4b11-bf07-dded65a5070d",
"name": "ワークフロー概要",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3376,
800
],
"parameters": {
"color": 7,
"width": 444,
"height": 760,
"content": "## COMPLETE WORKFLOW STRUCTURE\n\nMain Certificate Generation Flow:\n\n1. 📥 Webhook Trigger\n Receives JSON with certificate data\n\n2. 📧 Verifi Email\n Validates email address with VerifiEmail API\n\n3. ✅ IF Validation\n Checks: email valid + name/course/date not empty\n\n4. 🔄 Combine Data (Code node)\n Merges webhook data + email validation\n\n5. 🎨 Generate HTML Certificate (Code node)\n Creates beautiful HTML certificate\n\n6. 🖼️ HTML/CSS to Image\n Converts HTML → PNG image\n\n7. 📧 Send Email (Gmail)\n Delivers certificate to recipient\n\n8. 📊 Log to Google Sheets\n Records certificate details\n\nError Flow (Separate):\n• On Workflow Error → Format Error → Slack Alert\n\nStatus: ✅ Fully functional workflow\nMissing: Success response to webhook (recommended)\n\nAll credentials configured and tested"
},
"typeVersion": 1
},
{
"id": "7c4dc0c1-ae2b-4985-91de-a40356e28158",
"name": "テスト手順",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2896,
832
],
"parameters": {
"color": 7,
"width": 568,
"height": 856,
"content": "## 🧪 TESTING YOUR WORKFLOW\n\nWebhook URL:\nhttps://n8n.exildraw.com/webhook-test/certificate-generator\n\nTest with cURL:\n```\ncurl -X POST https://n8n.exildraw.com/webhook-test/certificate-generator \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"name\": \"Test User\",\n \"course\": \"Advanced JavaScript Programming\",\n \"date\": \"2025-10-04\",\n \"email\": \"test@gmail.com\",\n \"instructor\": \"Jane Smith\",\n \"duration\": \"40 hours\"\n }'\n```\nTest with Postman:\n1. Method: POST\n2. URL: [webhook URL above]\n3. Headers: Content-Type = application/json\n4. Body: Use JSON from curl example\n\nExpected Results:\n✅ Email validation passes\n✅ HTML certificate generated\n✅ Image created at HTMLcsstoImg\n✅ Email sent to recipient\n✅ Entry logged in Google Sheets\n✅ All nodes execute successfully\n\nValidation Test (should fail):\n• Missing required field\n• Invalid email format\n• Disposable email address\n\n⚠️ Note: Use real email addresses for testing\nexample.com won't pass MX record validation\n\nCurrent Status: All nodes configured and ready\nNext: Add \"Respond to Webhook\" for success response"
},
"typeVersion": 1
},
{
"id": "b9b4ba6f-35ca-4733-9d0a-0e2a7da5b56e",
"name": "HTML/CSS to Image",
"type": "n8n-nodes-htmlcsstoimage.htmlCssToImage",
"position": [
-160,
528
],
"parameters": {
"html_content": "={{ $json.html }}"
},
"credentials": {
"htmlcsstoimgApi": {
"id": "",
"name": "Htmlcsstoimg API"
}
},
"typeVersion": 1
},
{
"id": "de9c267d-d005-43d4-bbb3-c33370f9493a",
"name": "Verifi Email",
"type": "n8n-nodes-verifiemail.verifiEmail",
"position": [
-1872,
544
],
"parameters": {
"email": "={{ $json.body.email }}"
},
"credentials": {
"verifiEmailApi": {
"id": "",
"name": "VerifiEmail API"
}
},
"typeVersion": 1
},
{
"id": "646e0a7b-2cdc-48c0-8f15-5b7755e9e484",
"name": "If",
"type": "n8n-nodes-base.if",
"position": [
-1392,
544
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "a39497f8-8b8a-4b3a-bc5f-3e8738fa4cbb",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $('Certificate Request Webhook').item.json.body.name }}",
"rightValue": ""
},
{
"id": "37e0295c-18b2-4d3f-998b-e9d669dd90f7",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $('Certificate Request Webhook').item.json.body.course }}",
"rightValue": ""
},
{
"id": "6ecb1197-b460-402e-99a1-00edb0d5150c",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $('Certificate Request Webhook').item.json.body.date }}",
"rightValue": ""
},
{
"id": "3828fe0a-7c6a-449a-b380-c754717e0731",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $json.valid }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "9b7e5242-b3da-4552-b088-d585ffe7bcb0",
"name": "Stop and Error",
"type": "n8n-nodes-base.stopAndError",
"position": [
-1040,
784
],
"parameters": {
"errorMessage": "=\"Missing required fields: name, course, date, or valid email\""
},
"typeVersion": 1
},
{
"id": "b57d3884-9846-4b1f-9b00-ec378ea386ac",
"name": "Code in JavaScript",
"type": "n8n-nodes-base.code",
"position": [
-1056,
528
],
"parameters": {
"jsCode": "// Combine Webhook Data with Email Validation\n// Get the current item (from IF node - email validation data)\nconst emailData = $input.item.json;\n\n// Get the original webhook data from the first node\nconst webhookData = $('Certificate Request Webhook').first().json.body;\n\n// Combine everything\nreturn {\n json: {\n // Certificate data from webhook\n name: webhookData.name,\n course: webhookData.course,\n date: webhookData.date,\n email: webhookData.email,\n instructor: webhookData.instructor || 'Program Director',\n duration: webhookData.duration || '',\n certificateId: webhookData.certificateId || '',\n \n // Email validation results (optional - for logging/debugging)\n emailValidation: {\n valid: emailData.valid,\n provider: emailData.details.mx.provider,\n rfcCompliant: emailData.details.rfcCompliant,\n validMxRecord: emailData.details.validMxRecord,\n disposable: emailData.details.disposable\n }\n }\n};"
},
"typeVersion": 2
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "",
"connections": {
"646e0a7b-2cdc-48c0-8f15-5b7755e9e484": {
"main": [
[
{
"node": "b57d3884-9846-4b1f-9b00-ec378ea386ac",
"type": "main",
"index": 0
}
],
[
{
"node": "9b7e5242-b3da-4552-b088-d585ffe7bcb0",
"type": "main",
"index": 0
}
]
]
},
"de9c267d-d005-43d4-bbb3-c33370f9493a": {
"main": [
[
{
"node": "646e0a7b-2cdc-48c0-8f15-5b7755e9e484",
"type": "main",
"index": 0
}
]
]
},
"b9b4ba6f-35ca-4733-9d0a-0e2a7da5b56e": {
"main": [
[
{
"node": "7acdd47b-7014-4e0f-8b44-5acf326412be",
"type": "main",
"index": 0
}
]
]
},
"429a6ac5-d269-4176-ac81-d65117df54dd": {
"main": [
[
{
"node": "e3cc736c-3a91-42d5-9037-5ffcad3e8cab",
"type": "main",
"index": 0
}
]
]
},
"b57d3884-9846-4b1f-9b00-ec378ea386ac": {
"main": [
[
{
"node": "d2f582b7-9d23-43b9-bc05-e50f96ad122f",
"type": "main",
"index": 0
}
]
]
},
"e3cc736c-3a91-42d5-9037-5ffcad3e8cab": {
"main": [
[
{
"node": "c1ec5078-2bc7-4f7d-b413-fa0ca7691a15",
"type": "main",
"index": 0
}
]
]
},
"7acdd47b-7014-4e0f-8b44-5acf326412be": {
"main": [
[
{
"node": "37b407ee-9362-402a-b708-5c821e1e1116",
"type": "main",
"index": 0
}
]
]
},
"d2f582b7-9d23-43b9-bc05-e50f96ad122f": {
"main": [
[
{
"node": "b9b4ba6f-35ca-4733-9d0a-0e2a7da5b56e",
"type": "main",
"index": 0
}
]
]
},
"a8b8e036-c01d-4091-b817-43611a1e2643": {
"main": [
[
{
"node": "de9c267d-d005-43d4-bbb3-c33370f9493a",
"type": "main",
"index": 0
}
]
]
}
}
}よくある質問
このワークフローの使い方は?
上記のJSON設定コードをコピーし、n8nインスタンスで新しいワークフローを作成して「JSONからインポート」を選択、設定を貼り付けて認証情報を必要に応じて変更してください。
このワークフローはどんな場面に適していますか?
上級 - コンテンツ作成, マルチモーダルAI
有料ですか?
このワークフローは完全無料です。ただし、ワークフローで使用するサードパーティサービス(OpenAI APIなど)は別途料金が発生する場合があります。
関連ワークフロー
顧客の入社メール検証
VerifiEmail、Gmail、Slackを使用した自動メール検証と入社フロー
If
Code
Gmail
+
If
Code
Gmail
21 ノードJitesh Dugar
コンテンツ作成
インフルエンサー広告施策管理システムの自動化
Instagram / YouTube API を使ったインフルエンサー評価とイベント管理の自動化
If
Code
Gmail
+
If
Code
Gmail
24 ノードJitesh Dugar
コンテンツ作成
詐欺防止型リードキャプチャ・育成千リードシステム
AIによるスコアリング、テーブル追跡、マルチチャネルアラートを使って詐欺対策リードをキャプチャーし育成
If
Set
Code
+
If
Set
Code
28 ノードJitesh Dugar
コンテンツ作成
検証済み製品の返品ガイドジェネレーター
メール検証、PDF/画像生成、QRコードを使用した EC 返品ガイドの自動化
Set
Code
Gmail
+
Set
Code
Gmail
23 ノードJitesh Dugar
コンテンツ作成
検証済みゲストパス生成ツール
メール検証、パスと Slack リマインダーを使用した訪問者管理の自動化
If
Set
Code
+
If
Set
Code
22 ノードJitesh Dugar
文書抽出
会議議事録とアクションアイテムトラッカー
AIベースの会議議事録:GPT-4の活用、タスク割り当て、マルチチャネル配信
If
Set
Code
+
If
Set
Code
38 ノードJitesh Dugar
コンテンツ作成
ワークフロー情報
難易度
上級
ノード数25
カテゴリー2
ノードタイプ11
作成者
Jitesh Dugar
@jiteshdugarAI Automation Specialist - OpenAI, CRM & Automation Expert with a solid understanding of various tools that include Zapier, Make, Zoho CRM, Hubspot, Google Sheets, Airtable, Pipedrive, Google Analytics, and more.
外部リンク
n8n.ioで表示 →
このワークフローを共有