This workflow corresponds to n8n.io template #11747 — 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 →
{
"id": "",
"meta": {
"templateCredsSetupCompleted": false
},
"name": "Website Compliance Checker",
"tags": [],
"nodes": [
{
"id": "b6309f75-16ff-4027-930a-e245d4527ae2",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
1152,
384
],
"parameters": {
"path": "compliance-check",
"options": {},
"httpMethod": "POST",
"responseMode": "lastNode"
},
"typeVersion": 2.1
},
{
"id": "3d5000e0-da5e-42e8-a1dd-4ca2b8c8a905",
"name": "Fetch Website HTML",
"type": "n8n-nodes-base.httpRequest",
"position": [
1328,
384
],
"parameters": {
"url": "={{ $json.body.url }}",
"options": {
"timeout": 30000,
"redirect": {
"redirect": {}
},
"response": {
"response": {
"responseFormat": "text"
}
},
"allowUnauthorizedCerts": false
}
},
"typeVersion": 4.3
},
{
"id": "eadbf52b-6d3b-47e4-8c84-8a3d2f570384",
"name": "Extract & Clean HTML",
"type": "n8n-nodes-base.code",
"position": [
1536,
384
],
"parameters": {
"jsCode": " const html = $input.first().json.data;\n const url = $('Webhook').first().json.body.url;\n \n // Extract text content and remove excessive whitespace\n const cleanedHtml = html\n .replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '')\n .replace(/<style\\b[^<]*(?:(?!<\\/style>)<[^<]*)*<\\/style>/gi, '')\n .replace(/\\s+/g, ' ')\n .substring(0, 50000); // Limit to ~50k characters\n \n return {\n json: {\n url: url,\n html_content: cleanedHtml,\n original_url: url,\n email: $('Webhook').first().json.body.email,\n company_name: $('Webhook').first().json.body.company_name\n }\n };"
},
"typeVersion": 2
},
{
"id": "f8ec7ef2-e95c-462e-8217-33e5eeb4eb57",
"name": "Analyze Compliance",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
1808,
384
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "chatgpt-4o-latest",
"cachedResultName": "CHATGPT-4O-LATEST"
},
"options": {
"maxTokens": 2000,
"temperature": 0.3
},
"responses": {
"values": [
{
"role": "system",
"content": "= You are a website compliance auditor. Analyze the provided website HTML and check for:\n \n 1. Privacy Policy (presence, accessibility, GDPR/CCPA compliance indicators)\n 2. Cookie Consent (banner, management options)\n 3. Terms of Service\n 4. Accessibility (WCAG indicators like alt text, ARIA labels)\n 5. Contact Information (required in many jurisdictions)\n 6. SSL Certificate (from URL)\n 7. Data Protection Officer mention (for GDPR)\n \n Return ONLY a valid JSON object with this exact structure:\n {\n \"privacy_policy\": {\"found\": true/false, \"score\": 0-100, \"details\": \"string\"},\n \"cookie_consent\": {\"found\": true/false, \"score\": 0-100, \"details\": \"string\"},\n \"terms_of_service\": {\"found\": true/false, \"score\": 0-100, \"details\": \"string\"},\n \"accessibility\": {\"score\": 0-100, \"details\": \"string\", \"issues\": [\"string\"]},\n \"contact_info\": {\"found\": true/false, \"details\": \"string\"},\n \"ssl_enabled\": true/false,\n \"overall_score\": 0-100,\n \"critical_issues\": [\"string\"],\n \"recommendations\": [\"string\"]\n }"
},
{
"content": "= Website URL: {{ $json.url }}\n \n HTML Content:\n {{ $json.html_content }}\n \n Analyze this website for compliance."
}
]
},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "a3af2653-c410-4c0f-a85a-41f1ef810835",
"name": "Parse Compliance Results",
"type": "n8n-nodes-base.code",
"position": [
2128,
384
],
"parameters": {
"jsCode": "// Get the ChatGPT response\nconst chatGptOutput = $input.first().json.output[0].content[0].text;\n\n// Extract JSON from markdown code blocks\nlet complianceData;\ntry {\n // Remove markdown code blocks (```json and ```)\n const cleanedResponse = chatGptOutput\n .replace(/```json\\n?/g, '')\n .replace(/```\\n?/g, '')\n .trim();\n \n // Parse the JSON\n complianceData = JSON.parse(cleanedResponse);\n \n console.log('\u2705 Successfully parsed compliance data');\n} catch (error) {\n console.error('\u274c Failed to parse JSON:', error.message);\n \n // Fallback structure\n complianceData = {\n privacy_policy: { found: false, score: 0, details: \"Error parsing response\" },\n cookie_consent: { found: false, score: 0, details: \"Error parsing response\" },\n terms_of_service: { found: false, score: 0, details: \"Error parsing response\" },\n accessibility: { score: 0, details: \"Error parsing response\", issues: [] },\n contact_info: { found: false, details: \"Error parsing response\" },\n ssl_enabled: false,\n overall_score: 0,\n critical_issues: [\"Failed to parse compliance data: \" + error.message],\n recommendations: [\"Please retry the scan\"],\n error: true,\n raw_response: chatGptOutput\n };\n}\n\n// Get original webhook data\nconst webhookData = $('Webhook').first().json.body;\n\n// Return enriched data\nreturn {\n json: {\n ...complianceData,\n website_url: webhookData.url,\n company_name: webhookData.company_name,\n email: webhookData.email,\n scan_date: new Date().toISOString(),\n scan_timestamp: Date.now(),\n has_error: complianceData.error || false\n }\n};"
},
"typeVersion": 2
},
{
"id": "87d9dbb6-b104-4756-bed8-41d079c62191",
"name": "Generate HTML Report",
"type": "n8n-nodes-base.code",
"position": [
2384,
384
],
"parameters": {
"jsCode": "const data = $input.first().json;\n\n// Helper function to get score color\nconst getScoreColor = (score) => {\n if (score >= 70) return 'linear-gradient(135deg, #11998e 0%, #38ef7d 100%)';\n if (score >= 40) return 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)';\n return 'linear-gradient(135deg, #fa709a 0%, #fee140 100%)';\n};\n\n// Helper function to get score badge class\nconst getScoreBadge = (score) => {\n if (score >= 70) return 'score-high';\n if (score >= 40) return 'score-medium';\n return 'score-low';\n};\n\n// Format date\nconst formatDate = (isoDate) => {\n const date = new Date(isoDate);\n return date.toLocaleDateString('en-US', { \n year: 'numeric', \n month: 'long', \n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n};\n\n// Generate HTML\nconst html = `<!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>Website Compliance Report - ${data.company_name}</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica', 'Arial', sans-serif;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n padding: 40px 20px;\n color: #333;\n line-height: 1.6;\n }\n .container {\n max-width: 900px;\n margin: 0 auto;\n background: white;\n border-radius: 20px;\n box-shadow: 0 20px 60px rgba(0,0,0,0.3);\n overflow: hidden;\n }\n .header {\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n padding: 40px;\n text-align: center;\n }\n .header h1 { \n font-size: 32px; \n margin-bottom: 10px;\n font-weight: 700;\n }\n .header p { \n opacity: 0.9; \n font-size: 16px;\n margin: 5px 0;\n }\n .score-section {\n padding: 40px;\n text-align: center;\n background: #f8f9fa;\n border-bottom: 3px solid #e9ecef;\n }\n .score-circle {\n width: 150px;\n height: 150px;\n border-radius: 50%;\n margin: 0 auto 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 48px;\n font-weight: bold;\n color: white;\n background: ${getScoreColor(data.overall_score)};\n box-shadow: 0 10px 30px rgba(0,0,0,0.2);\n }\n .score-label {\n color: #333;\n font-size: 20px;\n font-weight: 600;\n margin-bottom: 10px;\n }\n .score-description {\n color: #666;\n font-size: 16px;\n }\n .content { padding: 40px; }\n .section {\n margin-bottom: 30px;\n padding: 25px;\n background: #f8f9fa;\n border-radius: 12px;\n border-left: 4px solid #667eea;\n }\n .section h2 {\n color: #667eea;\n margin-bottom: 15px;\n font-size: 22px;\n font-weight: 600;\n }\n .check-item {\n display: flex;\n align-items: flex-start;\n margin-bottom: 15px;\n padding: 15px;\n background: white;\n border-radius: 8px;\n box-shadow: 0 2px 4px rgba(0,0,0,0.05);\n }\n .icon {\n width: 28px;\n height: 28px;\n margin-right: 15px;\n flex-shrink: 0;\n font-size: 20px;\n font-weight: bold;\n }\n .icon.pass { color: #38ef7d; }\n .icon.fail { color: #f5576c; }\n .check-content {\n flex: 1;\n }\n .check-content h3 {\n font-size: 16px;\n margin-bottom: 8px;\n color: #333;\n font-weight: 600;\n }\n .check-content p {\n font-size: 14px;\n color: #666;\n line-height: 1.6;\n }\n .score-badge {\n display: inline-block;\n padding: 4px 12px;\n border-radius: 12px;\n font-size: 12px;\n font-weight: bold;\n margin-left: 10px;\n }\n .score-high { \n background: #d4edda; \n color: #155724; \n }\n .score-medium { \n background: #fff3cd; \n color: #856404; \n }\n .score-low { \n background: #f8d7da; \n color: #721c24; \n }\n .recommendations {\n background: #fff3cd;\n border-left-color: #ffc107;\n }\n .critical {\n background: #f8d7da;\n border-left-color: #dc3545;\n }\n ul {\n margin: 10px 0 0 20px;\n }\n li {\n margin-bottom: 8px;\n color: #666;\n font-size: 14px;\n }\n .footer {\n text-align: center;\n padding: 30px;\n background: #f8f9fa;\n color: #666;\n font-size: 14px;\n border-top: 2px solid #e9ecef;\n }\n .footer p {\n margin: 5px 0;\n }\n .website-info {\n background: white;\n padding: 20px;\n border-radius: 8px;\n margin-top: 15px;\n text-align: left;\n }\n .website-info strong {\n color: #667eea;\n }\n </style>\n</head>\n<body>\n <div class=\"container\">\n <div class=\"header\">\n <h1>\ud83d\udd12 Website Compliance Report</h1>\n <p style=\"font-size: 20px; font-weight: 600; margin-top: 15px;\">${data.company_name}</p>\n <p style=\"font-size: 14px; opacity: 0.8;\">${data.website_url}</p>\n <p style=\"margin-top: 15px; font-size: 13px;\">Generated on ${formatDate(data.scan_date)}</p>\n </div>\n \n <div class=\"score-section\">\n <div class=\"score-circle\">${data.overall_score}<span style=\"font-size: 24px;\">/100</span></div>\n <div class=\"score-label\">Overall Compliance Score</div>\n <p class=\"score-description\">\n ${data.overall_score >= 70 ? '\u2713 Good compliance standing' : \n data.overall_score >= 40 ? '\u26a0 Needs improvement' : \n '\u274c Critical issues detected'}\n </p>\n </div>\n \n <div class=\"content\">\n <!-- Privacy Policy -->\n <div class=\"section\">\n <h2>\ud83d\udd10 Privacy Policy</h2>\n <div class=\"check-item\">\n <span class=\"icon ${data.privacy_policy.found ? 'pass' : 'fail'}\">\n ${data.privacy_policy.found ? '\u2713' : '\u2717'}\n </span>\n <div class=\"check-content\">\n <h3>\n ${data.privacy_policy.found ? 'Privacy Policy Found' : 'Privacy Policy Missing'}\n <span class=\"score-badge ${getScoreBadge(data.privacy_policy.score)}\">\n ${data.privacy_policy.score}/100\n </span>\n </h3>\n <p>${data.privacy_policy.details}</p>\n </div>\n </div>\n </div>\n \n <!-- Cookie Consent -->\n <div class=\"section\">\n <h2>\ud83c\udf6a Cookie Consent</h2>\n <div class=\"check-item\">\n <span class=\"icon ${data.cookie_consent.found ? 'pass' : 'fail'}\">\n ${data.cookie_consent.found ? '\u2713' : '\u2717'}\n </span>\n <div class=\"check-content\">\n <h3>\n ${data.cookie_consent.found ? 'Cookie Banner Detected' : 'Cookie Banner Missing'}\n <span class=\"score-badge ${getScoreBadge(data.cookie_consent.score)}\">\n ${data.cookie_consent.score}/100\n </span>\n </h3>\n <p>${data.cookie_consent.details}</p>\n </div>\n </div>\n </div>\n \n <!-- Terms of Service -->\n <div class=\"section\">\n <h2>\ud83d\udcc4 Terms of Service</h2>\n <div class=\"check-item\">\n <span class=\"icon ${data.terms_of_service.found ? 'pass' : 'fail'}\">\n ${data.terms_of_service.found ? '\u2713' : '\u2717'}\n </span>\n <div class=\"check-content\">\n <h3>\n ${data.terms_of_service.found ? 'Terms of Service Found' : 'Terms of Service Missing'}\n <span class=\"score-badge ${getScoreBadge(data.terms_of_service.score)}\">\n ${data.terms_of_service.score}/100\n </span>\n </h3>\n <p>${data.terms_of_service.details}</p>\n </div>\n </div>\n </div>\n \n <!-- Accessibility -->\n <div class=\"section\">\n <h2>\u267f Accessibility (WCAG)</h2>\n <div class=\"check-item\">\n <span class=\"icon ${data.accessibility.score >= 70 ? 'pass' : 'fail'}\">\n ${data.accessibility.score >= 70 ? '\u2713' : '\u2717'}\n </span>\n <div class=\"check-content\">\n <h3>\n Accessibility Score\n <span class=\"score-badge ${getScoreBadge(data.accessibility.score)}\">\n ${data.accessibility.score}/100\n </span>\n </h3>\n <p>${data.accessibility.details}</p>\n ${data.accessibility.issues && data.accessibility.issues.length > 0 ? \n '<ul>' + data.accessibility.issues.map(issue => `<li>${issue}</li>`).join('') + '</ul>' \n : ''}\n </div>\n </div>\n </div>\n \n <!-- Contact Information -->\n <div class=\"section\">\n <h2>\ud83d\udce7 Contact Information</h2>\n <div class=\"check-item\">\n <span class=\"icon ${data.contact_info.found ? 'pass' : 'fail'}\">\n ${data.contact_info.found ? '\u2713' : '\u2717'}\n </span>\n <div class=\"check-content\">\n <h3>${data.contact_info.found ? 'Contact Info Available' : 'Contact Info Missing'}</h3>\n <p>${data.contact_info.details}</p>\n </div>\n </div>\n </div>\n \n <!-- SSL Certificate -->\n <div class=\"section\">\n <h2>\ud83d\udd12 SSL Certificate</h2>\n <div class=\"check-item\">\n <span class=\"icon ${data.ssl_enabled ? 'pass' : 'fail'}\">\n ${data.ssl_enabled ? '\u2713' : '\u2717'}\n </span>\n <div class=\"check-content\">\n <h3>${data.ssl_enabled ? 'HTTPS Enabled' : 'HTTPS Not Detected'}</h3>\n <p>${data.ssl_enabled ? 'Website is using secure HTTPS protocol' : 'Website should implement SSL/TLS encryption'}</p>\n </div>\n </div>\n </div>\n \n <!-- Critical Issues -->\n ${data.critical_issues && data.critical_issues.length > 0 ? `\n <div class=\"section critical\">\n <h2>\u26a0\ufe0f Critical Issues</h2>\n <ul>\n ${data.critical_issues.map(issue => `<li><strong>${issue}</strong></li>`).join('')}\n </ul>\n </div>\n ` : ''}\n \n <!-- Recommendations -->\n ${data.recommendations && data.recommendations.length > 0 ? `\n <div class=\"section recommendations\">\n <h2>\ud83d\udca1 Recommendations</h2>\n <ul>\n ${data.recommendations.map(rec => `<li>${rec}</li>`).join('')}\n </ul>\n </div>\n ` : ''}\n </div>\n \n <div class=\"footer\">\n <p><strong>Automated AI-Powered Compliance Report</strong></p>\n <p style=\"margin-top: 10px;\">This report was generated using artificial intelligence to scan and analyze website compliance.</p>\n <p style=\"margin-top: 5px; font-size: 12px; color: #999;\">\n \u26a0\ufe0f This is an automated assessment. For legal compliance advice, please consult with a qualified attorney.\n </p>\n <p style=\"margin-top: 15px; font-size: 12px;\">\n \u00a9 ${new Date().getFullYear()} Website Compliance Checker\n </p>\n </div>\n </div>\n</body>\n</html>`;\n\nreturn [{\n json: {\n ...data,\n html_report: html\n }\n}];"
},
"typeVersion": 2
},
{
"id": "4375bd77-ac97-4359-b4cb-9fea217a8df4",
"name": "HTML to PDF",
"type": "n8n-nodes-htmlcsstopdf.htmlcsstopdf",
"position": [
2592,
384
],
"parameters": {
"html_content": "={{ $json.html_report }}",
"output_format": "file",
"output_filename": "data"
},
"credentials": {
"htmlcsstopdfApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "8e1b7609-23c3-4ab1-b4b4-b911e2296cc2",
"name": "Send Compliance Report",
"type": "n8n-nodes-base.gmail",
"position": [
2864,
272
],
"parameters": {
"sendTo": "={{ $('Generate HTML Report').item.json.email }}",
"message": "=<div style=\"font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; background: #f8f9fa;\">\n <div style=\"background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center; border-radius: 10px 10px 0 0;\">\n <h1 style=\"margin: 0; font-size: 28px;\">\ud83d\udd12 Compliance Report Ready</h1>\n </div>\n \n <div style=\"padding: 30px; background: white;\">\n <p style=\"font-size: 16px; color: #333;\">Hello,</p>\n \n <p style=\"margin-top: 15px; font-size: 15px; color: #666;\">\n We've completed a comprehensive compliance scan of <strong style=\"color: #667eea;\">{{ $('Generate HTML Report').item.json.website_url }}</strong>\n </p>\n \n <div style=\"background: #f8f9fa; padding: 25px; border-radius: 8px; margin: 25px 0; text-align: center; border: 2px solid #e9ecef;\">\n <h2 style=\"color: #333; margin: 0 0 10px 0; font-size: 18px;\">Overall Compliance Score</h2>\n <div style=\"font-size: 56px; font-weight: bold; color: {{ $('Generate HTML Report').item.json.overall_score >= 70 ? '#38ef7d' : $('Generate HTML Report').item.json.overall_score >= 40 ? '#ffc107' : '#f5576c' }}; margin: 10px 0;\">\n {{ $('Generate HTML Report').item.json.overall_score }}<span style=\"font-size: 28px; color: #999;\">/100</span>\n </div>\n <p style=\"color: #666; font-size: 14px; margin-top: 10px;\">\n {{ $('Generate HTML Report').item.json.overall_score >= 70 ? '\u2713 Good compliance standing' : $('Generate HTML Report').item.json.overall_score >= 40 ? '\u26a0 Needs improvement' : '\u274c Critical issues detected' }}\n </p>\n </div>\n \n <h3 style=\"color: #333; font-size: 18px; margin: 25px 0 15px 0;\">\ud83d\udcca Quick Summary:</h3>\n <table style=\"width: 100%; border-collapse: collapse;\">\n <tr style=\"border-bottom: 1px solid #e9ecef;\">\n <td style=\"padding: 12px 0; color: #666;\">Privacy Policy</td>\n <td style=\"padding: 12px 0; text-align: right; font-weight: bold; color: {{ $('Generate HTML Report').item.json.privacy_policy.found ? '#38ef7d' : '#f5576c' }};\">\n {{ $('Generate HTML Report').item.json.privacy_policy.found ? '\u2713 Found' : '\u2717 Missing' }}\n </td>\n </tr>\n <tr style=\"border-bottom: 1px solid #e9ecef;\">\n <td style=\"padding: 12px 0; color: #666;\">Cookie Consent</td>\n <td style=\"padding: 12px 0; text-align: right; font-weight: bold; color: {{ $('Generate HTML Report').item.json.cookie_consent.found ? '#38ef7d' : '#f5576c' }};\">\n {{ $('Generate HTML Report').item.json.cookie_consent.found ? '\u2713 Found' : '\u2717 Missing' }}\n </td>\n </tr>\n <tr style=\"border-bottom: 1px solid #e9ecef;\">\n <td style=\"padding: 12px 0; color: #666;\">Terms of Service</td>\n <td style=\"padding: 12px 0; text-align: right; font-weight: bold; color: {{ $('Generate HTML Report').item.json.terms_of_service ? '#38ef7d' : '#f5576c' }};\">\n {{ $('Generate HTML Report').item.json.terms_of_service.found ? '\u2713 Found' : '\u2717 Missing' }}\n </td>\n </tr>\n <tr style=\"border-bottom: 1px solid #e9ecef;\">\n <td style=\"padding: 12px 0; color: #666;\">Accessibility Score</td>\n <td style=\"padding: 12px 0; text-align: right; font-weight: bold; color: #667eea;\">\n {{$('Generate HTML Report').item.json.accessibility.score}}/100\n </td>\n </tr>\n <tr>\n <td style=\"padding: 12px 0; color: #666;\">SSL Certificate</td>\n <td style=\"padding: 12px 0; text-align: right; font-weight: bold; color: {{ $('Generate HTML Report').item.json.ssl_enabled? '#38ef7d' : '#f5576c' }};\">\n {{ $('Generate HTML Report').item.json.ssl_enabled ? '\u2713 Enabled' : '\u2717 Not Detected' }}\n </td>\n </tr>\n </table>\n \n {{$('Generate HTML Report').item.json.critical_issues && $('Generate HTML Report').item.json.critical_issues.length > 0 ? '<div style=\"background: #f8d7da; border-left: 4px solid #dc3545; padding: 20px; margin: 25px 0; border-radius: 4px;\"><strong style=\"color: #721c24; font-size: 16px;\">\u26a0\ufe0f Critical Issues Detected:</strong><ul style=\"margin: 15px 0 0 0; padding-left: 20px;\">' + $('Generate HTML Report').item.json.critical_issues.map(issue => '<li style=\"color: #721c24; margin: 8px 0;\">' + issue + '</li>').join('') + '</ul></div>' : '' }}\n \n <p style=\"margin-top: 25px; color: #666; font-size: 15px;\">\n \ud83d\udcce Please find the <strong>detailed PDF report attached</strong> to this email with complete analysis and recommendations.\n </p>\n \n <div style=\"margin-top: 30px; padding-top: 25px; border-top: 2px solid #e9ecef;\">\n <p style=\"color: #999; font-size: 13px; text-align: center;\">\n This is an automated compliance scan powered by AI.<br>\n For legal compliance advice, please consult with a qualified attorney.\n </p>\n </div>\n </div>\n</div>",
"options": {
"attachmentsUi": {
"attachmentsBinary": [
{
"property": "=data"
}
]
}
},
"subject": "=\ud83d\udd12 Website Compliance Report - {{ $('Generate HTML Report').item.json.company_name }}"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 2.2
},
{
"id": "ada15969-b785-4e39-a1a4-c91fd8565afc",
"name": "Save to Google Drive",
"type": "n8n-nodes-base.googleDrive",
"position": [
2864,
448
],
"parameters": {
"name": "=Compliance_Report_{{ $('Generate HTML Report').item.json.company_name }}_{{ new Date().toISOString().split('T')[0] }}.pdf",
"driveId": {
"__rl": true,
"mode": "list",
"value": "My Drive"
},
"options": {},
"folderId": {
"__rl": true,
"mode": "list",
"value": "root",
"cachedResultName": "YOUR_FOLDER_NAME"
}
},
"credentials": {
"googleDriveOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 3
},
{
"id": "35be5b7b-75ae-4cae-8cd7-bf684c64fb9b",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
656,
-16
],
"parameters": {
"width": 432,
"height": 544,
"content": "### How it works\nThis workflow automatically audits websites for legal compliance. It receives a website URL via webhook, fetches and cleans the HTML content, uses OpenAI to analyze compliance across privacy policies, cookie consent, terms of service, accessibility (WCAG), SSL certificates, and contact information. The AI generates a comprehensive compliance report with scores and recommendations, converts it to PDF, emails it to the requester, and saves a copy to Google Drive for record-keeping.\n\n### Setup steps\nConnect these credentials before running:\n* **OpenAI** - Analyze website compliance\n* **HTMLCSS to PDF** - Convert reports to PDF\n* **Gmail** - Send compliance reports\n* **Google Drive** - Store PDF reports\n\n### Customization\nModify AI compliance criteria in \"Analyze Compliance\" node system prompt. Customize HTML report design in \"Generate HTML Report\" node. Adjust PDF styling via HTMLCSS to PDF settings. Configure email templates in \"Send Compliance Report\" for branded messaging."
},
"typeVersion": 1
},
{
"id": "4c257a6e-1878-4a82-9f0e-9860674e4105",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1120,
272
],
"parameters": {
"color": 7,
"width": 640,
"height": 240,
"content": "## Input & Website Scan\nWebhook receives website URL, company name, and email. Fetches HTML content and cleans it for AI analysis."
},
"typeVersion": 1
},
{
"id": "1c9e88a6-29ca-4f09-9977-91f786757d23",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2336,
272
],
"parameters": {
"color": 7,
"width": 432,
"height": 272,
"content": "## Report Generation\nBuilds professional HTML compliance report with scores and recommendations, then converts to downloadable PDF."
},
"typeVersion": 1
},
{
"id": "e0d8d4b6-0d69-4d38-a24a-c2eb81210917",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1776,
272
],
"parameters": {
"color": 7,
"width": 544,
"height": 288,
"content": "## AI Compliance Analysis\nOpenAI checks privacy policy, cookies, terms, SSL, accessibility, and contact info. Generates scores and identifies critical issues."
},
"typeVersion": 1
},
{
"id": "d3798123-f4ec-4d2e-b04c-10f566419ce6",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2784,
160
],
"parameters": {
"color": 7,
"width": 336,
"height": 448,
"content": "## Delivery & Storage\nEmails PDF report to user and saves copy to Google Drive for auditing and legal review purposes."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "",
"connections": {
"Webhook": {
"main": [
[
{
"node": "Fetch Website HTML",
"type": "main",
"index": 0
}
]
]
},
"HTML to PDF": {
"main": [
[
{
"node": "Save to Google Drive",
"type": "main",
"index": 0
},
{
"node": "Send Compliance Report",
"type": "main",
"index": 0
}
]
]
},
"Analyze Compliance": {
"main": [
[
{
"node": "Parse Compliance Results",
"type": "main",
"index": 0
}
]
]
},
"Fetch Website HTML": {
"main": [
[
{
"node": "Extract & Clean HTML",
"type": "main",
"index": 0
}
]
]
},
"Extract & Clean HTML": {
"main": [
[
{
"node": "Analyze Compliance",
"type": "main",
"index": 0
}
]
]
},
"Generate HTML Report": {
"main": [
[
{
"node": "HTML to PDF",
"type": "main",
"index": 0
}
]
]
},
"Save to Google Drive": {
"main": [
[]
]
},
"Send Compliance Report": {
"main": [
[]
]
},
"Parse Compliance Results": {
"main": [
[
{
"node": "Generate HTML Report",
"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.
gmailOAuth2googleDriveOAuth2ApihtmlcsstopdfApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automate website compliance checks in minutes using AI-powered analysis. This workflow scans any website for essential legal and accessibility requirements, generates a professional compliance report, delivers it as a PDF, and stores it securely — helping teams identify risks…
Source: https://n8n.io/workflows/11747/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Fully automated meeting documentation workflow that uses AI to transform raw transcripts into professional PDFs and actionable tasks. AI-powered summary generation (GPT-4) Automatic action item extrac
Automatically transform resolved support tickets into professional, AI-powered PDF documentation with complete tracking and team notifications.
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
This workflow automates the entire parent consent process for school field trips, replacing manual paper forms with a secure, verified, and legally compliant digital system.
Transform new hire onboarding from 3-4 hours of manual document compilation to 3 minutes of automated generation - creates personalized, role-specific document packages including welcome letters, bene