This workflow corresponds to n8n.io template #10829 — we link there as the canonical source.
This workflow follows the Agent → Chat Trigger 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": "nMN0reA9rvuZwAjK",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Generate SEO Content Briefs from Chat Input Using AI, DataForSEO, SERP Analysis & Google Sheets",
"tags": [],
"nodes": [
{
"id": "cc7d2183-d9b9-4a7c-8806-fdcb0b7600e9",
"name": "Overview Sticky",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1632,
-720
],
"parameters": {
"width": 420,
"height": 464,
"content": "## \ud83d\udcdd AI-Powered SEO Content Brief Generator\n\n### How it works\nThis workflow generates comprehensive, data-driven SEO content briefs using real-time keyword research, competitor analysis, and SERP intelligence. An AI agent analyzes search volume, keyword difficulty, content gaps, and competitor strategies to create briefs with quality scoring, versioning, and HTML previews. All briefs are automatically stored in Google Sheets with version control.\n\n### Setup steps\n1. **Connect credentials**: OpenAI API, DataForSEO, SerpAPI, Google Sheets OAuth2\n2. **Configure Google Sheet**: Create sheets named `content_versions` with columns: content_id, version_no, version_id, topic, meta_title, meta_desc, outline, keywords, tone, word_count, cta_ideas, context_used, timestamp\n3. **Set Slack webhook** (optional): Replace webhook URL in \"Send Quality Alert\" node for low-quality brief notifications\n4. **Test the workflow**: Send a topic via chat trigger and review the generated brief\n\n*Note: This workflow uses GPT-4o-mini for cost-effective brief generation with consistent quality.*"
},
"typeVersion": 1
},
{
"id": "911f0520-7d91-4799-ba5c-ee1982c1b70f",
"name": "Input Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1632,
-240
],
"parameters": {
"color": 2,
"width": 512,
"height": 412,
"content": "## \ud83c\udfaf Input Normalization\n\nStandardizes incoming chat messages into a consistent format (intent, topic, content, parameters) for downstream processing."
},
"typeVersion": 1
},
{
"id": "795c77cc-e0fc-4f17-b337-3b257372bfea",
"name": "Keyword Research Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1104,
-240
],
"parameters": {
"color": 2,
"height": 412,
"content": "## \ud83d\udd0d Keyword Research\n\nFetches real-time search volume, keyword difficulty, and CPC data from DataForSEO to inform brief recommendations."
},
"typeVersion": 1
},
{
"id": "b19ec937-6190-49e7-bc89-0da3f764030e",
"name": "AI Agent Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
-848,
-224
],
"parameters": {
"color": 2,
"width": 720,
"height": 676,
"content": "## \ud83e\udd16 AI Brief Generation\n\nThe AI agent combines keyword data, SERP analysis, competitor intelligence, and historical content from Google Sheets to generate comprehensive briefs with structured JSON output."
},
"typeVersion": 1
},
{
"id": "fede1c25-bc4f-4df5-9062-5c3c3858181d",
"name": "Quality & Storage Section",
"type": "n8n-nodes-base.stickyNote",
"position": [
-112,
-256
],
"parameters": {
"color": 2,
"width": 908,
"height": 708,
"content": "## \u2705 Quality Control & Storage\n\nCalculates quality scores across SEO, differentiation, and completeness dimensions. Validates briefs against minimum thresholds, generates HTML previews, and stores approved briefs in Google Sheets with version control."
},
"typeVersion": 1
},
{
"id": "f148b18c-1712-4c4b-8c6e-1e5d08e770b6",
"name": "Credentials Info",
"type": "n8n-nodes-base.stickyNote",
"position": [
816,
128
],
"parameters": {
"color": 3,
"width": 320,
"height": 312,
"content": "## \ud83d\udd10 Required Credentials\n\n- **OpenAI API**: For GPT-4o-mini brief generation\n- **DataForSEO**: Basic auth for keyword metrics\n- **SerpAPI**: For real-time SERP analysis\n- **Google Sheets OAuth2**: For context retrieval and brief storage\n- **Slack Webhook** (optional): For quality alerts\n\nReplace all placeholder credentials before activating."
},
"typeVersion": 1
},
{
"id": "0cfadf9c-3630-4494-8ba7-90812810f532",
"name": "Short-Term Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
-624,
256
],
"parameters": {
"sessionKey": "brief-writer-session",
"sessionIdType": "customKey"
},
"typeVersion": 1.3
},
{
"id": "26e1bb40-3465-46c4-9cbf-3f97477f2d40",
"name": "AI Agent (Brief Writer)",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
-560,
16
],
"parameters": {
"text": "=Topic: {{ $('Normalize Input').item.json.intent }}\nIntent: {{ $('Normalize Input').item.json.intent }}\nUser request: {{ $('Normalize Input').item.json.content }}\n\nKeyword Data: {{ $('Get Keyword Metrics').item.json || 'No keyword data' }}\n\nContext (from Sheets): {{ $json.context || 'No context found' }}",
"options": {
"systemMessage": "=You are \"Brief Writer Agent\", a senior SEO content strategist AI.\n\nYou have access to:\n1. Keyword metrics (volume, difficulty, CPC)\n2. Deep competitor analysis (headings, word counts)\n3. Content gap opportunities\n4. Internal linking suggestions\n5. Entity and semantic analysis\n6. SERP Intelligence\n7. Historical content from Sheets\n\n\ud83c\udfaf ENHANCED BRIEF GENERATION\n\n**Use Keyword Data:**\n- Prioritize high volume + low difficulty\n- Include CPC for commercial intent\n- Add LSI keywords from entities\n\n**Use Competitor Analysis:**\n- Match or exceed word count by 15-20%\n- Improve on common H2 patterns\n- Exploit competitor weaknesses\n\n**Use Content Gaps:**\n- Create H2s for missed topics\n- Address unanswered PAA questions\n- Include unique angles\n\n**Use Internal Links:**\n- Suggest 3-5 related articles\n- Include anchor text recommendations\n\n\ud83d\udcc4 VERSIONING\n1. Check Sheets for existing topic\n2. If exists: reuse content_id, increment version_no\n3. If new: create CNT-<timestamp>, version_no = 1\n\n\ud83d\udce4 OUTPUT FORMAT\n\n{\n \"brief\": {\n \"title\": \"string\",\n \"meta_description\": \"string\",\n \"target_keywords\": [\n {\n \"keyword\": \"string\",\n \"volume\": number,\n \"difficulty\": number,\n \"priority\": \"primary|secondary\"\n }\n ],\n \"outline\": [\n {\n \"h2\": \"string\",\n \"h3_suggestions\": [\"string\"],\n \"purpose\": \"competitor_match|content_gap|paa_answer\"\n }\n ],\n \"word_count\": number,\n \"tone\": \"string\",\n \"cta_ideas\": [\"string\"],\n \"internal_links\": [\n {\n \"anchor_text\": \"string\",\n \"target_content_id\": \"string\",\n \"relevance_score\": number\n }\n ],\n \"semantic_entities\": [\"string\"],\n \"content_gaps_addressed\": [\"string\"]\n },\n \"competitive_intel\": {\n \"avg_competitor_word_count\": number,\n \"top_3_competitors\": [\"string\"],\n \"our_advantage\": [\"string\"],\n \"difficulty_assessment\": \"easy|medium|hard\"\n },\n \"metadata\": {\n \"content_id\": \"string\",\n \"version_no\": number,\n \"version_id\": \"string\",\n \"is_new_topic\": boolean\n },\n \"quality_scores\": {\n \"seo_score\": number,\n \"differentiation_score\": number,\n \"completeness_score\": number,\n \"overall_score\": number\n },\n \"context_used\": [\"string\"]\n}\n\n\ud83d\udccc RULES\n- Use ALL data sources\n- Data-driven decisions\n- If competitor avg is 2000 words, recommend 2300-2400\n- Address 3+ content gaps\n- Include entities in keywords\n- Calculate quality scores\n- Return JSON ONLY"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2.1
},
{
"id": "6a888524-27de-400a-ac65-795ac9c39d59",
"name": "Structured JSON Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
-240,
256
],
"parameters": {
"jsonSchemaExample": "{\n \"brief\": {\n \"title\": \"string\",\n \"meta_description\": \"string\",\n \"target_keywords\": [{\"keyword\": \"string\", \"volume\": 1000, \"difficulty\": 45, \"priority\": \"primary\"}],\n \"outline\": [{\"h2\": \"string\", \"h3_suggestions\": [\"string\"], \"purpose\": \"content_gap\"}],\n \"word_count\": 2500,\n \"tone\": \"string\",\n \"cta_ideas\": [\"string\"],\n \"internal_links\": [{\"anchor_text\": \"string\", \"target_content_id\": \"string\", \"relevance_score\": 8}],\n \"semantic_entities\": [\"string\"],\n \"content_gaps_addressed\": [\"string\"]\n },\n \"competitive_intel\": {\n \"avg_competitor_word_count\": 2000,\n \"top_3_competitors\": [\"string\"],\n \"our_advantage\": [\"string\"],\n \"difficulty_assessment\": \"medium\"\n },\n \"metadata\": {\n \"content_id\": \"CNT-001\",\n \"version_no\": 1,\n \"version_id\": \"VER-001\",\n \"is_new_topic\": true\n },\n \"quality_scores\": {\n \"seo_score\": 8.5,\n \"differentiation_score\": 7.0,\n \"completeness_score\": 9.0,\n \"overall_score\": 8.2\n },\n \"context_used\": [\"serp\", \"keywords\", \"competitors\", \"sheets\"]\n}"
},
"typeVersion": 1.3
},
{
"id": "2f106b07-7da8-4c1b-bdb5-7a9149102fbf",
"name": "Retrieve Historical Content Context",
"type": "n8n-nodes-base.googleSheetsTool",
"position": [
-496,
256
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": 2120745354,
"cachedResultName": "content_versions"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1fsnnXsU1n-iX-MEpLuw3XC6wHD-ek6OlkQe31ousk84",
"cachedResultName": "SEO Content Automation"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "485c1a47-f406-49cd-84dd-2a2cb08401b8",
"name": "Validate Brief Quality",
"type": "n8n-nodes-base.if",
"position": [
208,
32
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"id": "quality-check-1",
"operator": {
"type": "number",
"operation": "largerEqual"
},
"leftValue": "={{ $json.output.brief.outline.length }}",
"rightValue": 5
},
{
"id": "quality-check-2",
"operator": {
"type": "number",
"operation": "largerEqual"
},
"leftValue": "={{ $json.output.brief.target_keywords.length }}",
"rightValue": 3
},
{
"id": "quality-check-3",
"operator": {
"type": "number",
"operation": "largerEqual"
},
"leftValue": "={{ $json.output.brief.word_count }}",
"rightValue": 800
},
{
"id": "quality-check-4",
"operator": {
"type": "number",
"operation": "largerEqual"
},
"leftValue": "={{ $json.output.quality_scores.overall_score }}",
"rightValue": 6
},
{
"id": "7d55c376-2f47-4a12-8379-ab3477c83236",
"operator": {
"type": "number",
"operation": "gt"
},
"leftValue": "={{ $json.output.quality_scores.overall_score }}",
"rightValue": 8
}
]
}
},
"typeVersion": 2
},
{
"id": "9aa6edbb-ab73-4d74-b74b-76d4394f08b6",
"name": "Store Brief with Version Control",
"type": "n8n-nodes-base.googleSheets",
"position": [
656,
-80
],
"parameters": {
"columns": {
"value": {
"tone": "={{ $json.output.brief.tone }}",
"topic": "={{ $('Normalize Input').item.json.topic }}",
"outline": "={{ JSON.stringify($json.output.brief.outline) }}",
"keywords": "={{ JSON.stringify($json.output.brief.target_keywords) }}",
"cta_ideas": "={{ JSON.stringify($json.output.brief.cta_ideas) }}",
"meta_desc": "={{ $json.output.brief.meta_description }}",
"timestamp": "={{ $now }}",
"content_id": "={{ $json.output.metadata.content_id }}",
"meta_title": "={{ $json.output.brief.title }}",
"version_id": "={{ $json.output.metadata.version_id }}",
"version_no": "={{ $json.output.metadata.version_no }}",
"word_count": "={{ $json.output.brief.word_count }}",
"context_used": "={{ JSON.stringify($json.output.context_used) }}"
},
"schema": [
{
"id": "content_id",
"type": "string",
"display": true,
"required": false,
"displayName": "content_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "version_no",
"type": "string",
"display": true,
"required": false,
"displayName": "version_no",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "version_id",
"type": "string",
"display": true,
"required": false,
"displayName": "version_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "topic",
"type": "string",
"display": true,
"required": false,
"displayName": "topic",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "meta_title",
"type": "string",
"display": true,
"required": false,
"displayName": "meta_title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "meta_desc",
"type": "string",
"display": true,
"required": false,
"displayName": "meta_desc",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "outline",
"type": "string",
"display": true,
"required": false,
"displayName": "outline",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "keywords",
"type": "string",
"display": true,
"required": false,
"displayName": "keywords",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "tone",
"type": "string",
"display": true,
"required": false,
"displayName": "tone",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "word_count",
"type": "string",
"display": true,
"required": false,
"displayName": "word_count",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "cta_ideas",
"type": "string",
"display": true,
"required": false,
"displayName": "cta_ideas",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "context_used",
"type": "string",
"display": true,
"required": false,
"displayName": "context_used",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "timestamp",
"type": "string",
"display": true,
"required": false,
"displayName": "timestamp",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "section",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "section",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "html",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "html",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"timestamp"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "appendOrUpdate",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 2120745354,
"cachedResultName": "content_versions"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1fsnnXsU1n-iX-MEpLuw3XC6wHD-ek6OlkQe31ousk84",
"cachedResultName": "SEO Content Automation"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "4ad12b1b-6d88-4e44-9ecf-46c40c0931fb",
"name": "OpenAI GPT-4o-mini Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-752,
256
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "8d102000-1d1f-4adc-9d6c-1b4f95894852",
"name": "Normalize Input",
"type": "n8n-nodes-base.set",
"position": [
-1264,
16
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "8ea18d06-f3cb-4988-9015-d1baec5f74c1",
"name": "intent",
"type": "string",
"value": "={{ $json.intent || 'brief' }}"
},
{
"id": "f091b1a0-2d42-4ade-b25d-9d562cad239f",
"name": "topic",
"type": "string",
"value": "={{ $json.topic || $json.chatInput }}"
},
{
"id": "4ce9bf82-c89e-44e8-aca6-4720fdf6dcf7",
"name": "content",
"type": "string",
"value": "={{ $json.content || '' }}"
},
{
"id": "cef206d3-24f5-46c4-bab4-bbe246ef655e",
"name": "parameter",
"type": "object",
"value": "={{ $json.parameter || {} }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "6bd7c780-daf0-4044-b79d-83b2aac46eaa",
"name": "SERP Analysis Tool",
"type": "@n8n/n8n-nodes-langchain.toolSerpApi",
"position": [
-368,
256
],
"parameters": {
"options": {}
},
"credentials": {
"serpApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "d729bf90-d5d8-4639-bf1d-95588d7aaf1d",
"name": "Chat Trigger",
"type": "@n8n/n8n-nodes-langchain.chatTrigger",
"position": [
-1552,
16
],
"parameters": {
"options": {}
},
"typeVersion": 1.3
},
{
"id": "cbd4a16a-2bee-429e-b2a6-330147f27264",
"name": "Fetch Keyword Metrics from DataForSEO",
"type": "n8n-nodes-base.httpRequest",
"notes": "Fetches search volume, keyword difficulty, and CPC data",
"position": [
-1040,
16
],
"parameters": {
"url": "https://api.dataforseo.com/v3/keywords_data/google/search_volume/live",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "keywords",
"value": "=[\"{{ $('Normalize Input').item.json.topic }}\"]"
},
{
"name": "language_code",
"value": "=en"
},
{
"name": "location_code",
"value": "=2840"
}
]
},
"genericAuthType": "httpBasicAuth"
},
"credentials": {
"httpBasicAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "a45a5bb2-12e3-4667-8700-5fdc6596f07f",
"name": "Calculate Quality Scores",
"type": "n8n-nodes-base.code",
"position": [
-32,
32
],
"parameters": {
"jsCode": "const brief = $input.first().json.output.brief;\nconst competitive = $input.first().json.output.competitive_intel;\n\nlet seoScore = 0;\nif (brief.target_keywords && brief.target_keywords.length >= 5) seoScore += 3;\nif (brief.meta_description && brief.meta_description.length <= 160) seoScore += 2;\nif (brief.title && brief.title.length <= 60) seoScore += 2;\nif (brief.outline && brief.outline.length >= 7) seoScore += 2;\nif (brief.semantic_entities && brief.semantic_entities.length >= 5) seoScore += 1;\n\nlet diffScore = 0;\nif (brief.content_gaps_addressed && brief.content_gaps_addressed.length >= 3) diffScore += 4;\nif (competitive.our_advantage && competitive.our_advantage.length >= 2) diffScore += 3;\nif (brief.word_count > competitive.avg_competitor_word_count) diffScore += 3;\n\nlet completeScore = 0;\nif (brief.outline && brief.outline.length >= 5) completeScore += 2;\nif (brief.cta_ideas && brief.cta_ideas.length >= 2) completeScore += 2;\nif (brief.internal_links && brief.internal_links.length >= 3) completeScore += 2;\nif (brief.target_keywords && brief.target_keywords.length >= 3) completeScore += 2;\nif (brief.semantic_entities && brief.semantic_entities.length >= 5) completeScore += 2;\n\nconst overallScore = ((seoScore + diffScore + completeScore) / 3).toFixed(1);\n\nreturn {\n json: {\n ...$input.first().json,\n output: {\n ...$input.first().json.output,\n quality_scores: {\n seo_score: seoScore,\n differentiation_score: diffScore,\n completeness_score: completeScore,\n overall_score: parseFloat(overallScore)\n }\n }\n }\n};"
},
"typeVersion": 2
},
{
"id": "cb585b9f-8a79-4fd1-bedd-abb7843d3c08",
"name": "Send Slack Quality Alert",
"type": "n8n-nodes-base.httpRequest",
"position": [
432,
128
],
"parameters": {
"url": "https://hooks.slack.com/services/[YOUR_WEBHOOK_URL]",
"method": "POST",
"options": {},
"jsonBody": "={\n \"text\": \"\u26a0\ufe0f Brief Quality Check Failed\",\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"*Brief Generation Alert*\\nTopic: {{ $('Normalize Input').item.json.topic }}\\nQuality Score: {{ $('Calculate Quality Scores').item.json.output.quality_scores.overall_score }}\"\n }\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.2
},
{
"id": "2927e7c9-a9f5-4899-961f-895d48eee343",
"name": "Generate HTML Preview",
"type": "n8n-nodes-base.code",
"position": [
432,
-80
],
"parameters": {
"jsCode": "const output = $input.first().json.output;\nconst brief = output.brief;\nconst competitive = output.competitive_intel;\nconst quality = output.quality_scores;\nconst metadata = output.metadata;\n\nconst keywordsHtml = brief.target_keywords.map(kw => \n typeof kw === 'object' \n ? `<span class=\"keyword ${kw.priority === 'primary' ? 'primary' : ''}\">${kw.keyword} ${kw.volume ? `(${kw.volume})` : ''}</span>`\n : `<span class=\"keyword\">${kw}</span>`\n).join('');\n\nconst outlineHtml = brief.outline.map(section => \n typeof section === 'object'\n ? `<li><strong>${section.h2}</strong> <span class=\"purpose\">${section.purpose || ''}</span>\n ${section.h3_suggestions && section.h3_suggestions.length > 0 ? `<ul style=\"margin-top: 8px;\">${section.h3_suggestions.map(h3 => `<li style=\"border:none; background:transparent; padding:5px 0;\">${h3}</li>`).join('')}</ul>` : ''}\n </li>`\n : `<li>${section}</li>`\n).join('');\n\nconst html = `<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <title>Brief Preview - ${brief.title}</title>\n <style>\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; max-width: 900px; margin: 40px auto; padding: 20px; background: #f5f7fa; }\n .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; border-radius: 12px; margin-bottom: 30px; }\n .header h1 { margin: 0 0 10px 0; font-size: 32px; }\n .header .meta { opacity: 0.9; font-size: 14px; }\n .card { background: white; padding: 25px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }\n .card h2 { margin: 0 0 15px 0; font-size: 20px; color: #2d3748; border-bottom: 2px solid #667eea; padding-bottom: 10px; }\n .keywords { display: flex; flex-wrap: wrap; gap: 8px; margin: 15px 0; }\n .keyword { background: #edf2f7; padding: 6px 12px; border-radius: 20px; font-size: 13px; border: 1px solid #cbd5e0; }\n .keyword.primary { background: #667eea; color: white; border-color: #667eea; }\n .outline { list-style: none; padding: 0; }\n .outline li { padding: 12px; margin: 8px 0; background: #f7fafc; border-left: 4px solid #667eea; border-radius: 4px; }\n .outline li .purpose { font-size: 11px; color: #718096; margin-left: 10px; background: #edf2f7; padding: 2px 8px; border-radius: 10px; }\n .scores { display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; }\n .score-box { text-align: center; padding: 20px; background: #f7fafc; border-radius: 8px; border: 2px solid #e2e8f0; }\n .score-box .number { font-size: 36px; font-weight: bold; color: #667eea; }\n .score-box .label { font-size: 12px; color: #718096; margin-top: 5px; text-transform: uppercase; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>${brief.title}</h1>\n <div class=\"meta\">Content ID: ${metadata.content_id} | Version: ${metadata.version_no} | ${metadata.is_new_topic ? '\ud83c\udd95 New Topic' : '\ud83d\udd04 Updated'}</div>\n </div>\n <div class=\"card\">\n <h2>\ud83d\udcca Quality Scores</h2>\n <div class=\"scores\">\n <div class=\"score-box\"><div class=\"number\">${quality.overall_score}</div><div class=\"label\">Overall</div></div>\n <div class=\"score-box\"><div class=\"number\">${quality.seo_score}</div><div class=\"label\">SEO</div></div>\n <div class=\"score-box\"><div class=\"number\">${quality.differentiation_score}</div><div class=\"label\">Differentiation</div></div>\n <div class=\"score-box\"><div class=\"number\">${quality.completeness_score}</div><div class=\"label\">Completeness</div></div>\n </div>\n </div>\n <div class=\"card\">\n <h2>\ud83c\udfaf Meta Information</h2>\n <p><strong>Meta Description:</strong></p>\n <p style=\"background: #f7fafc; padding: 15px; border-radius: 6px;\">${brief.meta_description}</p>\n <p><strong>Word Count:</strong> ${brief.word_count} | <strong>Tone:</strong> ${brief.tone}</p>\n </div>\n <div class=\"card\">\n <h2>\ud83d\udd11 Target Keywords</h2>\n <div class=\"keywords\">${keywordsHtml}</div>\n </div>\n <div class=\"card\">\n <h2>\ud83d\udcdd Content Outline</h2>\n <ol class=\"outline\">${outlineHtml}</ol>\n </div>\n <div class=\"card\">\n <h2>\ud83c\udfc6 Competitive Intelligence</h2>\n <p><strong>Avg Competitor Words:</strong> ${competitive.avg_competitor_word_count || 'N/A'}</p>\n <p><strong>Difficulty:</strong> ${competitive.difficulty_assessment || 'N/A'}</p>\n </div>\n</body>\n</html>`;\n\nreturn {\n json: {\n html_preview: html,\n ...output\n },\n binary: {\n preview: {\n data: Buffer.from(html).toString('base64'),\n mimeType: 'text/html',\n fileName: `brief_${metadata.content_id}_${metadata.version_id}.html`\n }\n }\n};"
},
"typeVersion": 2
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "80898bbe-36e4-470f-87cd-2d6d34d89f44",
"connections": {
"Chat Trigger": {
"main": [
[
{
"node": "Normalize Input",
"type": "main",
"index": 0
}
]
]
},
"Normalize Input": {
"main": [
[
{
"node": "Fetch Keyword Metrics from DataForSEO",
"type": "main",
"index": 0
}
]
]
},
"Short-Term Memory": {
"ai_memory": [
[
{
"node": "AI Agent (Brief Writer)",
"type": "ai_memory",
"index": 0
}
]
]
},
"SERP Analysis Tool": {
"ai_tool": [
[
{
"node": "AI Agent (Brief Writer)",
"type": "ai_tool",
"index": 0
}
]
]
},
"Generate HTML Preview": {
"main": [
[
{
"node": "Store Brief with Version Control",
"type": "main",
"index": 0
}
]
]
},
"Validate Brief Quality": {
"main": [
[
{
"node": "Generate HTML Preview",
"type": "main",
"index": 0
}
],
[
{
"node": "Send Slack Quality Alert",
"type": "main",
"index": 0
}
]
]
},
"AI Agent (Brief Writer)": {
"main": [
[
{
"node": "Calculate Quality Scores",
"type": "main",
"index": 0
}
]
]
},
"Calculate Quality Scores": {
"main": [
[
{
"node": "Validate Brief Quality",
"type": "main",
"index": 0
}
]
]
},
"OpenAI GPT-4o-mini Model": {
"ai_languageModel": [
[
{
"node": "AI Agent (Brief Writer)",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Structured JSON Output Parser": {
"ai_outputParser": [
[
{
"node": "AI Agent (Brief Writer)",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Retrieve Historical Content Context": {
"ai_tool": [
[
{
"node": "AI Agent (Brief Writer)",
"type": "ai_tool",
"index": 0
}
]
]
},
"Fetch Keyword Metrics from DataForSEO": {
"main": [
[
{
"node": "AI Agent (Brief Writer)",
"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.
googleSheetsOAuth2ApihttpBasicAuthopenAiApiserpApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Generate high-quality, SEO-optimized content briefs automatically using AI, real-time keyword research, SERP intelligence, and historical content context. This workflow standardizes user inputs, fetches search metrics, analyzes competitors, and produces structured SEO briefs…
Source: https://n8n.io/workflows/10829/ — 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.
HDW Lead Geländewagen. Uses chatTrigger, lmChatOpenAi, memoryBufferWindow, outputParserStructured. Chat trigger; 92 nodes.
This comprehensive workflow automates the complete financial document processing pipeline using AI. Upload invoices via chat, drop expense receipts into a folder, or add bank statements - the system a
by Varritech Technologies
Who’s it for Creators who want to create faceless videos automatically, while keeping human oversight and quality control.
The Best Linkedin Posting System. Uses httpRequest, lmChatOpenAi, agent, chatTrigger. Chat trigger; 49 nodes.