| {"instruction": "What is Generative Engine Optimization (GEO) and how does it differ from traditional SEO?", "input": "", "output": "# Generative Engine Optimization (GEO)\n\n**Definition**: GEO is the practice of optimizing content to appear in AI-generated responses from systems like ChatGPT, Google AI Overview, Perplexity, and Claude.\n\n## Key Differences from Traditional SEO\n\n| Aspect | Traditional SEO | GEO |\n|--------|----------------|-----|\n| **Target** | Search engine results pages (SERPs) | AI-generated answers |\n| **Metrics** | Rankings, CTR, impressions | Citation frequency, source attribution |\n| **Content Style** | Keyword-focused | Comprehensive, authoritative |\n| **Structure** | Meta tags, headings | Semantic clarity, factual density |\n\n## Core GEO Strategies\n\n1. **Establish Topical Authority**\n - Create comprehensive pillar pages\n - Interlink related content\n - Cover topics exhaustively\n\n2. **Optimize for Citation**\n - Use clear, quotable statements\n - Include data, statistics, and facts\n - Cite authoritative sources\n\n3. **Structured Data Implementation**\n - JSON-LD schema markup\n - FAQ schema\n - HowTo schema\n - Organization schema\n\n4. **Content Format**\n - Use definition patterns: \"X is...\"\n - Include step-by-step instructions\n - Provide comparison tables\n - Add concrete examples\n\n## Implementation in n8n\n\n```json\n{\n \"nodes\": [\n {\n \"name\": \"Analyze Content for GEO\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"// Check GEO optimization score\\nconst content = $json.content;\\nconst score = {\\n hasDefinitions: /is a|refers to|means/i.test(content),\\n hasStats: /\\\\d+%|\\\\d+ percent/i.test(content),\\n hasSteps: /step \\\\d|first,|then,/i.test(content)\\n};\\nreturn { score };\"\n }\n }\n ]\n}\n```", "metadata": {"topic": "GEO", "type": "concept", "priority": "high"}} | |
| {"instruction": "How do I optimize content for Answer Engine Optimization (AEO) to appear in featured snippets?", "input": "", "output": "# Answer Engine Optimization (AEO) Guide\n\n**AEO** focuses on structuring content to directly answer user questions, targeting featured snippets and voice search results.\n\n## Featured Snippet Types & Optimization\n\n### 1. Paragraph Snippets (Most Common)\n- Target \"what is\", \"why\", \"how does\" queries\n- Provide 40-60 word direct answers\n- Place answer immediately after the H2\n\n**Example Structure**:\n```html\n<h2>What is Answer Engine Optimization?</h2>\n<p>Answer Engine Optimization (AEO) is the process of optimizing content \nto provide direct answers to user queries, increasing visibility in \nfeatured snippets, voice search results, and AI-generated responses.</p>\n```\n\n### 2. List Snippets\n- Use numbered or bulleted lists\n- Include 4-8 items\n- Start each item with action verbs\n\n### 3. Table Snippets\n- Use comparison tables\n- Include clear headers\n- Limit to 3-4 columns\n\n## AEO Implementation Checklist\n\n- [ ] Identify question-based keywords\n- [ ] Structure content with clear Q&A format\n- [ ] Use schema markup (FAQPage, HowTo)\n- [ ] Optimize for voice search (conversational)\n- [ ] Include \"People Also Ask\" targets\n\n## n8n Workflow for AEO Analysis\n\n```json\n{\n \"name\": \"AEO Content Analyzer\",\n \"nodes\": [\n {\n \"name\": \"Fetch Content\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"={{ $json.pageUrl }}\"\n }\n },\n {\n \"name\": \"Check FAQ Schema\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const html = $json.body;\\nconst hasFAQSchema = html.includes('FAQPage');\\nreturn { hasFAQSchema };\"\n }\n }\n ]\n}\n```\n\n## Voice Search Optimization Tips\n\n1. Use natural, conversational language\n2. Target long-tail question queries\n3. Optimize for local intent (\"near me\")\n4. Provide concise, speakable answers (< 30 words)", "metadata": {"topic": "AEO", "type": "guide", "priority": "high"}} | |
| {"instruction": "Explain LLM SEO strategies for getting cited by AI chatbots like ChatGPT and Claude", "input": "", "output": "# LLM SEO: Optimizing for AI Chatbot Citations\n\n**LLM SEO** is the emerging practice of optimizing content so Large Language Models cite your website in their responses.\n\n## How LLMs Choose Sources\n\n1. **Training Data**: Content that was in training datasets\n2. **RAG Systems**: Real-time retrieval from indexed sources\n3. **Authority Signals**: Domain reputation, backlinks, mentions\n4. **Content Quality**: Accuracy, depth, recency\n\n## Core LLM SEO Strategies\n\n### 1. Establish Entity Authority\n- Build Wikipedia presence\n- Get mentioned in authoritative sources\n- Create comprehensive \"About\" pages\n- Use consistent NAP (Name, Address, Phone)\n\n### 2. Create Citation-Worthy Content\n\n**Best Practices**:\n- Include original research and data\n- Provide unique insights not available elsewhere\n- Use clear, quotable statements\n- Update content regularly\n\n**Example Citation-Worthy Format**:\n```\nAccording to [Your Brand] research, 73% of marketers now \nprioritize AI search optimization in their 2025 strategy.\n```\n\n### 3. Technical Optimization\n\n```json\n{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Article\",\n \"author\": {\n \"@type\": \"Organization\",\n \"name\": \"Your Brand\",\n \"url\": \"https://yourdomain.com\"\n },\n \"datePublished\": \"2024-01-15\",\n \"dateModified\": \"2024-12-01\"\n}\n```\n\n### 4. Content Structure for LLM Parsing\n\n- Use clear hierarchical headings\n- Include TL;DR summaries at the top\n- Provide structured data (tables, lists)\n- Add glossary definitions\n\n## Measurement & Tracking\n\n| Metric | Tool | Target |\n|--------|------|--------|\n| Brand mentions in AI | Manual sampling | Track monthly |\n| Knowledge Panel presence | Google Search | Establish/maintain |\n| Authoritative backlinks | Ahrefs/Semrush | Increase 10%/quarter |\n\n## n8n Workflow: Monitor AI Citations\n\n```json\n{\n \"name\": \"AI Citation Monitor\",\n \"nodes\": [\n {\n \"name\": \"Query ChatGPT\",\n \"type\": \"n8n-nodes-base.openAi\",\n \"parameters\": {\n \"prompt\": \"Who are the leading experts in {{ $json.topic }}?\"\n }\n },\n {\n \"name\": \"Check for Brand Mention\",\n \"type\": \"n8n-nodes-base.if\",\n \"parameters\": {\n \"conditions\": {\n \"string\": [{\n \"value1\": \"={{ $json.response }}\",\n \"operation\": \"contains\",\n \"value2\": \"Your Brand\"\n }]\n }\n }\n }\n ]\n}\n```", "metadata": {"topic": "LLM_SEO", "type": "strategy", "priority": "high"}} | |
| {"instruction": "How do I create an automated SEO audit workflow in n8n?", "input": "", "output": "# Automated SEO Audit Workflow in n8n\n\nBuild a comprehensive SEO audit system that checks on-page, technical, and content factors.\n\n## Complete n8n Workflow\n\n```json\n{\n \"name\": \"Automated SEO Audit\",\n \"nodes\": [\n {\n \"name\": \"Start\",\n \"type\": \"n8n-nodes-base.manualTrigger\",\n \"position\": [250, 300]\n },\n {\n \"name\": \"Set URLs\",\n \"type\": \"n8n-nodes-base.set\",\n \"parameters\": {\n \"values\": {\n \"string\": [\n {\"name\": \"targetUrl\", \"value\": \"https://example.com\"}\n ]\n }\n },\n \"position\": [450, 300]\n },\n {\n \"name\": \"Fetch Page\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"={{ $json.targetUrl }}\",\n \"options\": {\"timeout\": 30000}\n },\n \"position\": [650, 300]\n },\n {\n \"name\": \"SEO Analysis\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const html = $json.body;\\nconst url = $json.targetUrl;\\n\\n// Extract SEO elements\\nconst titleMatch = html.match(/<title>([^<]+)<\\\\/title>/i);\\nconst h1Match = html.match(/<h1[^>]*>([^<]+)<\\\\/h1>/i);\\nconst metaDescMatch = html.match(/<meta[^>]*name=\\\"description\\\"[^>]*content=\\\"([^\\\"]+)\\\"/i);\\nconst canonicalMatch = html.match(/<link[^>]*rel=\\\"canonical\\\"[^>]*href=\\\"([^\\\"]+)\\\"/i);\\n\\n// Check for robots directives\\nconst hasNoIndex = /noindex/i.test(html);\\nconst hasNoFollow = /nofollow/i.test(html);\\n\\n// Count elements\\nconst h2Count = (html.match(/<h2/gi) || []).length;\\nconst imgCount = (html.match(/<img/gi) || []).length;\\nconst imgNoAlt = (html.match(/<img(?![^>]*alt=)/gi) || []).length;\\n\\n// Calculate scores\\nconst issues = [];\\nlet score = 100;\\n\\nif (!titleMatch) {\\n issues.push('Missing title tag');\\n score -= 15;\\n}\\nif (!h1Match) {\\n issues.push('Missing H1 tag');\\n score -= 10;\\n}\\nif (!metaDescMatch) {\\n issues.push('Missing meta description');\\n score -= 10;\\n}\\nif (hasNoIndex) {\\n issues.push('Page has noindex directive');\\n score -= 20;\\n}\\nif (imgNoAlt > 0) {\\n issues.push(`${imgNoAlt} images missing alt text`);\\n score -= imgNoAlt * 2;\\n}\\n\\nreturn {\\n url,\\n score: Math.max(0, score),\\n title: titleMatch ? titleMatch[1] : null,\\n h1: h1Match ? h1Match[1] : null,\\n metaDescription: metaDescMatch ? metaDescMatch[1] : null,\\n canonical: canonicalMatch ? canonicalMatch[1] : null,\\n h2Count,\\n imgCount,\\n imgNoAlt,\\n issues\\n};\"\n },\n \"position\": [850, 300]\n },\n {\n \"name\": \"Generate Report\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const data = $json;\\nconst report = `# SEO Audit Report\\n\\n**URL**: ${data.url}\\n**Score**: ${data.score}/100\\n\\n## Elements Found\\n- Title: ${data.title || 'MISSING'}\\n- H1: ${data.h1 || 'MISSING'}\\n- Meta Description: ${data.metaDescription ? 'Present' : 'MISSING'}\\n\\n## Issues Found\\n${data.issues.map(i => '- ' + i).join('\\\\n')}`\\n\\nreturn { report };\"\n },\n \"position\": [1050, 300]\n }\n ],\n \"connections\": {\n \"Start\": {\"main\": [[{\"node\": \"Set URLs\", \"type\": \"main\", \"index\": 0}]]},\n \"Set URLs\": {\"main\": [[{\"node\": \"Fetch Page\", \"type\": \"main\", \"index\": 0}]]},\n \"Fetch Page\": {\"main\": [[{\"node\": \"SEO Analysis\", \"type\": \"main\", \"index\": 0}]]},\n \"SEO Analysis\": {\"main\": [[{\"node\": \"Generate Report\", \"type\": \"main\", \"index\": 0}]]}\n }\n}\n```\n\n## Audit Checks Included\n\n1. **On-Page SEO**\n - Title tag presence and length\n - H1 tag presence\n - Meta description\n - Heading hierarchy\n\n2. **Technical SEO**\n - Canonical URL\n - Robots directives\n - Image alt text\n\n3. **Reporting**\n - Score calculation\n - Issue identification\n - Markdown report generation\n\n## Extended Integrations\n\n- **Ahrefs API**: Backlink analysis\n- **Google Search Console**: Search performance data\n- **PageSpeed Insights**: Core Web Vitals", "metadata": {"topic": "SEO_automation", "type": "workflow", "priority": "high"}} | |
| {"instruction": "How do I build a lead nurturing funnel in n8n with GoHighLevel?", "input": "", "output": "# Lead Nurturing Funnel: n8n + GoHighLevel Integration\n\nBuild an automated lead nurturing system that scores, segments, and nurtures leads based on behavior.\n\n## Architecture Overview\n\n```\nWebhook (Lead Capture) \u2192 Lead Scoring \u2192 Segment Assignment \u2192 Nurture Sequence\n \u2193\n Sales Alert \u2190 Hot Lead Detection \u2190 Engagement Tracking\n```\n\n## Complete Workflow\n\n```json\n{\n \"name\": \"GHL Lead Nurturing Funnel\",\n \"nodes\": [\n {\n \"name\": \"Webhook Trigger\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"parameters\": {\n \"path\": \"lead-capture\",\n \"httpMethod\": \"POST\"\n },\n \"position\": [250, 300]\n },\n {\n \"name\": \"Lead Scoring\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const lead = $json.body;\\nlet score = 0;\\n\\n// Score based on form data\\nif (lead.company_size > 100) score += 20;\\nif (lead.budget === 'high') score += 25;\\nif (lead.timeline === 'immediate') score += 20;\\nif (lead.source === 'referral') score += 15;\\n\\n// Score based on engagement\\nif (lead.pages_viewed > 5) score += 10;\\nif (lead.time_on_site > 300) score += 10;\\n\\nreturn { ...lead, leadScore: score, segment: score > 60 ? 'hot' : score > 30 ? 'warm' : 'cold' };\"\n },\n \"position\": [450, 300]\n },\n {\n \"name\": \"Route by Segment\",\n \"type\": \"n8n-nodes-base.switch\",\n \"parameters\": {\n \"rules\": {\n \"rules\": [\n {\"value\": \"hot\"},\n {\"value\": \"warm\"},\n {\"value\": \"cold\"}\n ]\n }\n },\n \"position\": [650, 300]\n },\n {\n \"name\": \"Add to GHL - Hot Pipeline\",\n \"type\": \"n8n-nodes-base.highLevel\",\n \"parameters\": {\n \"resource\": \"contact\",\n \"operation\": \"create\",\n \"additionalFields\": {\n \"pipelineId\": \"hot_lead_pipeline\",\n \"tags\": [\"hot-lead\", \"priority\"]\n }\n },\n \"position\": [850, 200]\n },\n {\n \"name\": \"Add to GHL - Warm Nurture\",\n \"type\": \"n8n-nodes-base.highLevel\",\n \"parameters\": {\n \"resource\": \"contact\",\n \"operation\": \"create\",\n \"additionalFields\": {\n \"workflowId\": \"nurture_sequence_warm\"\n }\n },\n \"position\": [850, 300]\n },\n {\n \"name\": \"Add to GHL - Cold Campaign\",\n \"type\": \"n8n-nodes-base.highLevel\",\n \"parameters\": {\n \"resource\": \"contact\",\n \"operation\": \"create\",\n \"additionalFields\": {\n \"workflowId\": \"nurture_sequence_cold\"\n }\n },\n \"position\": [850, 400]\n },\n {\n \"name\": \"Notify Sales Team\",\n \"type\": \"n8n-nodes-base.slack\",\n \"parameters\": {\n \"channel\": \"#sales-alerts\",\n \"text\": \"\ud83d\udd25 Hot Lead: {{ $json.email }}\\nScore: {{ $json.leadScore }}\\nCompany: {{ $json.company }}\"\n },\n \"position\": [1050, 200]\n }\n ]\n}\n```\n\n## Lead Scoring Framework\n\n| Factor | Points | Criteria |\n|--------|--------|----------|\n| Company Size | +20 | > 100 employees |\n| Budget | +25 | \"High\" selected |\n| Timeline | +20 | \"Immediate\" need |\n| Referral Source | +15 | Came from referral |\n| Page Views | +10 | > 5 pages viewed |\n| Time on Site | +10 | > 5 minutes |\n\n## Segment Actions\n\n**Hot Leads (60+ points)**:\n- Immediate sales notification\n- Add to priority pipeline\n- Direct outreach within 1 hour\n\n**Warm Leads (30-60 points)**:\n- 7-day email nurture sequence\n- Weekly value content\n- Retargeting ads\n\n**Cold Leads (<30 points)**:\n- Monthly newsletter\n- Educational content\n- Long-term nurturing", "metadata": {"topic": "marketing_automation", "type": "workflow", "priority": "high"}} | |
| {"instruction": "How do I track marketing ROI and CAC/LTV metrics with n8n?", "input": "", "output": "# Marketing ROI & Metrics Tracking with n8n\n\nBuild automated dashboards tracking Customer Acquisition Cost (CAC), Lifetime Value (LTV), and ROI.\n\n## Key Metrics Formulas\n\n```\nCAC = Total Marketing Spend / New Customers Acquired\nLTV = Average Revenue Per Customer \u00d7 Average Customer Lifespan\nROI = (Revenue - Marketing Spend) / Marketing Spend \u00d7 100\nLTV:CAC Ratio = LTV / CAC (Target: 3:1 or higher)\n```\n\n## n8n Workflow for ROI Tracking\n\n```json\n{\n \"name\": \"Marketing ROI Dashboard\",\n \"nodes\": [\n {\n \"name\": \"Schedule Trigger\",\n \"type\": \"n8n-nodes-base.scheduleTrigger\",\n \"parameters\": {\n \"rule\": {\"interval\": [{\"field\": \"weeks\", \"weeks\": 1}]}\n },\n \"position\": [250, 300]\n },\n {\n \"name\": \"Fetch Ad Spend - Google\",\n \"type\": \"n8n-nodes-base.googleAds\",\n \"parameters\": {\n \"operation\": \"getCampaigns\",\n \"dateRange\": \"LAST_30_DAYS\"\n },\n \"position\": [450, 200]\n },\n {\n \"name\": \"Fetch Ad Spend - Facebook\",\n \"type\": \"n8n-nodes-base.facebookAds\",\n \"parameters\": {\n \"operation\": \"getInsights\",\n \"datePreset\": \"last_30d\"\n },\n \"position\": [450, 400]\n },\n {\n \"name\": \"Fetch Revenue Data\",\n \"type\": \"n8n-nodes-base.supabase\",\n \"parameters\": {\n \"operation\": \"select\",\n \"table\": \"orders\",\n \"options\": {\n \"conditions\": \"created_at > NOW() - INTERVAL '30 days'\"\n }\n },\n \"position\": [450, 300]\n },\n {\n \"name\": \"Merge Data\",\n \"type\": \"n8n-nodes-base.merge\",\n \"parameters\": {\"mode\": \"append\"},\n \"position\": [650, 300]\n },\n {\n \"name\": \"Calculate Metrics\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const data = $json;\\n\\n// Aggregate spend\\nconst totalSpend = data.reduce((sum, item) => sum + (item.spend || 0), 0);\\n\\n// Count new customers\\nconst newCustomers = data.filter(item => item.type === 'order' && item.is_new_customer).length;\\n\\n// Calculate revenue\\nconst revenue = data.filter(item => item.type === 'order').reduce((sum, item) => sum + item.amount, 0);\\n\\n// Calculate metrics\\nconst CAC = newCustomers > 0 ? totalSpend / newCustomers : 0;\\nconst ROI = totalSpend > 0 ? ((revenue - totalSpend) / totalSpend * 100) : 0;\\nconst ROAS = totalSpend > 0 ? revenue / totalSpend : 0;\\n\\nreturn {\\n period: 'Last 30 Days',\\n totalSpend,\\n newCustomers,\\n revenue,\\n CAC: CAC.toFixed(2),\\n ROI: ROI.toFixed(1) + '%',\\n ROAS: ROAS.toFixed(2) + 'x'\\n};\"\n },\n \"position\": [850, 300]\n },\n {\n \"name\": \"Store in Database\",\n \"type\": \"n8n-nodes-base.supabase\",\n \"parameters\": {\n \"operation\": \"insert\",\n \"table\": \"marketing_metrics\"\n },\n \"position\": [1050, 200]\n },\n {\n \"name\": \"Send Report\",\n \"type\": \"n8n-nodes-base.slack\",\n \"parameters\": {\n \"channel\": \"#marketing\",\n \"text\": \"\ud83d\udcca Weekly Marketing Report\\n\\n\ud83d\udcb0 Spend: ${{ $json.totalSpend }}\\n\ud83d\udc65 New Customers: {{ $json.newCustomers }}\\n\ud83d\udcb5 Revenue: ${{ $json.revenue }}\\n\ud83d\udcc8 CAC: ${{ $json.CAC }}\\n\ud83c\udfaf ROI: {{ $json.ROI }}\\n\u21a9\ufe0f ROAS: {{ $json.ROAS }}\"\n },\n \"position\": [1050, 400]\n }\n ]\n}\n```\n\n## Attribution Models\n\n### Last-Touch Attribution\n```javascript\n// Credit the last interaction before conversion\nconst lastTouch = customer.interactions.slice(-1)[0];\nchannelCredits[lastTouch.channel] += 1;\n```\n\n### Linear Attribution\n```javascript\n// Equal credit to all touchpoints\nconst creditPerTouch = 1 / customer.interactions.length;\ncustomer.interactions.forEach(i => {\n channelCredits[i.channel] += creditPerTouch;\n});\n```\n\n### Time-Decay Attribution\n```javascript\n// More credit to recent interactions\ncustomer.interactions.forEach((interaction, index) => {\n const weight = Math.pow(2, index - customer.interactions.length + 1);\n channelCredits[interaction.channel] += weight;\n});\n```\n\n## Recommended Benchmarks\n\n| Metric | Good | Great | Excellent |\n|--------|------|-------|-----------|\n| LTV:CAC | 3:1 | 4:1 | 5:1+ |\n| ROI | 100% | 200% | 400%+ |\n| ROAS | 2x | 4x | 6x+ |\n| Payback Period | 12 mo | 6 mo | 3 mo |", "metadata": {"topic": "marketing_metrics", "type": "workflow", "priority": "high"}} | |
| {"instruction": "How do I set up multi-channel marketing automation with n8n?", "input": "", "output": "# Multi-Channel Marketing Automation with n8n\n\nOrchestrate campaigns across Email, SMS, WhatsApp, LinkedIn, and Paid Ads from a single workflow.\n\n## Channel Integration Architecture\n\n```\nCampaign Trigger \u2192 Audience Segmentation \u2192 Channel Router \u2192 Multi-Channel Delivery\n \u251c\u2500\u2500 Email (Mailchimp/SendGrid)\n \u251c\u2500\u2500 SMS (Twilio/MessageBird)\n \u251c\u2500\u2500 WhatsApp (360dialog)\n \u251c\u2500\u2500 LinkedIn (API)\n \u2514\u2500\u2500 Retargeting (FB/Google)\n```\n\n## Unified Campaign Workflow\n\n```json\n{\n \"name\": \"Multi-Channel Campaign\",\n \"nodes\": [\n {\n \"name\": \"Campaign Trigger\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"parameters\": {\n \"path\": \"campaign/launch\"\n },\n \"position\": [250, 300]\n },\n {\n \"name\": \"Fetch Audience\",\n \"type\": \"n8n-nodes-base.supabase\",\n \"parameters\": {\n \"operation\": \"select\",\n \"table\": \"contacts\",\n \"conditions\": \"segment = '{{ $json.targetSegment }}'\"\n },\n \"position\": [450, 300]\n },\n {\n \"name\": \"Split by Preference\",\n \"type\": \"n8n-nodes-base.splitInBatches\",\n \"position\": [650, 300]\n },\n {\n \"name\": \"Channel Router\",\n \"type\": \"n8n-nodes-base.switch\",\n \"parameters\": {\n \"rules\": {\n \"rules\": [\n {\"output\": 0, \"value\": \"email\"},\n {\"output\": 1, \"value\": \"sms\"},\n {\"output\": 2, \"value\": \"whatsapp\"},\n {\"output\": 3, \"value\": \"linkedin\"}\n ]\n },\n \"expression\": \"={{ $json.preferred_channel }}\"\n },\n \"position\": [850, 300]\n },\n {\n \"name\": \"Send Email\",\n \"type\": \"n8n-nodes-base.sendGrid\",\n \"parameters\": {\n \"toEmail\": \"={{ $json.email }}\",\n \"subject\": \"={{ $json.campaignSubject }}\",\n \"content\": \"={{ $json.campaignContent }}\"\n },\n \"position\": [1050, 100]\n },\n {\n \"name\": \"Send SMS\",\n \"type\": \"n8n-nodes-base.twilio\",\n \"parameters\": {\n \"to\": \"={{ $json.phone }}\",\n \"body\": \"={{ $json.smsContent }}\"\n },\n \"position\": [1050, 250]\n },\n {\n \"name\": \"Send WhatsApp\",\n \"type\": \"n8n-nodes-base.whatsApp\",\n \"parameters\": {\n \"to\": \"={{ $json.phone }}\",\n \"template\": \"campaign_template_1\"\n },\n \"position\": [1050, 400]\n },\n {\n \"name\": \"LinkedIn Outreach\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://api.linkedin.com/v2/messages\",\n \"method\": \"POST\"\n },\n \"position\": [1050, 550]\n },\n {\n \"name\": \"Merge Results\",\n \"type\": \"n8n-nodes-base.merge\",\n \"parameters\": {\"mode\": \"append\"},\n \"position\": [1250, 300]\n },\n {\n \"name\": \"Log Engagement\",\n \"type\": \"n8n-nodes-base.supabase\",\n \"parameters\": {\n \"operation\": \"insert\",\n \"table\": \"campaign_logs\"\n },\n \"position\": [1450, 300]\n }\n ]\n}\n```\n\n## Channel Best Practices\n\n### Email\n- Send Tuesday-Thursday, 10am-2pm\n- Subject line < 50 characters\n- Personalize with {{firstName}}\n- A/B test subject lines\n\n### SMS\n- Keep under 160 characters\n- Include clear CTA\n- Respect quiet hours (9am-9pm)\n- Provide opt-out\n\n### WhatsApp\n- Use approved templates\n- Rich media support\n- 24-hour response window\n- High open rates (98%)\n\n### LinkedIn\n- Personalize connection requests\n- Send InMail sequentially\n- Limit to 100 connections/week\n- Follow up within 3 days\n\n## Engagement Tracking\n\n```javascript\n// Track engagement across channels\nconst engagement = {\n email: {opens: 45, clicks: 12, ctr: 0.27},\n sms: {delivered: 100, responses: 8, rate: 0.08},\n whatsapp: {read: 98, replies: 15, rate: 0.15},\n linkedin: {accepted: 32, replies: 5, rate: 0.16}\n};\n\n// Calculate weighted engagement score\nconst channelWeights = {email: 1, sms: 1.2, whatsapp: 1.5, linkedin: 2};\nconst score = Object.keys(engagement).reduce((sum, ch) => \n sum + engagement[ch].rate * channelWeights[ch], 0\n);\n```", "metadata": {"topic": "multi_channel_marketing", "type": "workflow", "priority": "high"}} | |
| {"instruction": "How do I sync contacts between Odoo CRM and n8n for automated sales workflows?", "input": "", "output": "# Odoo CRM + n8n Integration for Sales Automation\n\nBidirectional sync between Odoo CRM and n8n for automated lead management, opportunity tracking, and sales workflows.\n\n## Odoo API Connection Setup\n\n```json\n{\n \"credentials\": {\n \"odoo\": {\n \"url\": \"https://your-instance.odoo.com\",\n \"database\": \"your_db\",\n \"username\": \"api_user\",\n \"password\": \"your_api_key\"\n }\n }\n}\n```\n\n## Sync Workflow: New Leads to Odoo\n\n```json\n{\n \"name\": \"Lead Capture to Odoo\",\n \"nodes\": [\n {\n \"name\": \"Webhook - New Lead\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"parameters\": {\n \"path\": \"lead-capture\",\n \"httpMethod\": \"POST\"\n },\n \"position\": [250, 300]\n },\n {\n \"name\": \"Create Odoo Lead\",\n \"type\": \"n8n-nodes-base.odoo\",\n \"parameters\": {\n \"resource\": \"lead\",\n \"operation\": \"create\",\n \"fields\": {\n \"name\": \"={{ $json.subject }}\",\n \"email_from\": \"={{ $json.email }}\",\n \"phone\": \"={{ $json.phone }}\",\n \"description\": \"={{ $json.message }}\",\n \"partner_name\": \"={{ $json.company }}\"\n }\n },\n \"position\": [450, 300]\n },\n {\n \"name\": \"Assign Sales Team\",\n \"type\": \"n8n-nodes-base.odoo\",\n \"parameters\": {\n \"resource\": \"lead\",\n \"operation\": \"update\",\n \"leadId\": \"={{ $json.id }}\",\n \"fields\": {\n \"team_id\": \"={{ $json.region === 'west' ? 1 : 2 }}\",\n \"user_id\": \"={{ $json.assignedRep }}\"\n }\n },\n \"position\": [650, 300]\n },\n {\n \"name\": \"Create Activity\",\n \"type\": \"n8n-nodes-base.odoo\",\n \"parameters\": {\n \"resource\": \"activity\",\n \"operation\": \"create\",\n \"fields\": {\n \"res_model\": \"crm.lead\",\n \"res_id\": \"={{ $json.lead_id }}\",\n \"activity_type_id\": 2,\n \"summary\": \"Initial follow-up call\",\n \"date_deadline\": \"={{ $today.plus({days: 1}).toISODate() }}\"\n }\n },\n \"position\": [850, 300]\n }\n ]\n}\n```\n\n## Opportunity Stage Updates\n\n```json\n{\n \"name\": \"Monitor Odoo Stage Changes\",\n \"nodes\": [\n {\n \"name\": \"Poll Odoo\",\n \"type\": \"n8n-nodes-base.odoo\",\n \"parameters\": {\n \"resource\": \"lead\",\n \"operation\": \"getAll\",\n \"filters\": {\n \"write_date\": \">={{ $now.minus({minutes: 5}).toISO() }}\"\n }\n }\n },\n {\n \"name\": \"Check Stage Change\",\n \"type\": \"n8n-nodes-base.if\",\n \"parameters\": {\n \"conditions\": {\n \"string\": [{\n \"value1\": \"={{ $json.stage_id }}\",\n \"operation\": \"equals\",\n \"value2\": \"Won\"\n }]\n }\n }\n },\n {\n \"name\": \"Trigger Onboarding\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"parameters\": {\n \"method\": \"POST\",\n \"url\": \"https://n8n.example.com/webhook/onboarding\"\n }\n }\n ]\n}\n```\n\n## Odoo Models Reference\n\n| Model | Description | Key Fields |\n|-------|-------------|------------|\n| `crm.lead` | Leads & Opportunities | name, email_from, phone, stage_id |\n| `res.partner` | Contacts & Companies | name, email, phone, is_company |\n| `mail.activity` | Tasks & Activities | res_model, res_id, activity_type_id |\n| `sale.order` | Sales Orders | partner_id, amount_total, state |\n\n## Error Handling\n\n```javascript\n// Handle Odoo API errors\ntry {\n const result = await odooClient.create('crm.lead', leadData);\n return { success: true, id: result };\n} catch (error) {\n if (error.code === 'DUPLICATE') {\n // Find existing and update instead\n const existing = await odooClient.search('crm.lead', [['email_from', '=', leadData.email_from]]);\n await odooClient.update('crm.lead', existing[0], leadData);\n } else {\n throw error;\n }\n}\n```", "metadata": {"topic": "odoo_integration", "type": "workflow", "priority": "high"}} | |
| {"instruction": "What are the best practices for implementing exponential backoff in n8n workflows?", "input": "", "output": "# Exponential Backoff Implementation in n8n\n\nExponential backoff is crucial for handling rate limits, temporary failures, and API quotas gracefully.\n\n## Exponential Backoff Theory\n\n```\nWait Time = base_delay \u00d7 (2 ^ attempt_number) + random_jitter\n```\n\n**Example with 1s base delay**:\n- Attempt 1: 1s\n- Attempt 2: 2s\n- Attempt 3: 4s\n- Attempt 4: 8s\n- Attempt 5: 16s\n\n## n8n Implementation\n\n### Method 1: Built-in Retry Settings\n\n```json\n{\n \"name\": \"HTTP Request with Retry\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://api.example.com/data\"\n },\n \"retryOnFail\": true,\n \"maxTries\": 5,\n \"waitBetweenTries\": 1000,\n \"continueOnFail\": false\n}\n```\n\n### Method 2: Custom Exponential Backoff\n\n```json\n{\n \"name\": \"Exponential Backoff Workflow\",\n \"nodes\": [\n {\n \"name\": \"Initialize\",\n \"type\": \"n8n-nodes-base.set\",\n \"parameters\": {\n \"values\": {\"number\": [\n {\"name\": \"attempt\", \"value\": 0},\n {\"name\": \"maxAttempts\", \"value\": 5},\n {\"name\": \"baseDelay\", \"value\": 1000}\n ]}\n }\n },\n {\n \"name\": \"Make Request\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://api.example.com/data\"\n },\n \"continueOnFail\": true\n },\n {\n \"name\": \"Check Success\",\n \"type\": \"n8n-nodes-base.if\",\n \"parameters\": {\n \"conditions\": {\n \"number\": [{\n \"value1\": \"={{ $json.statusCode }}\",\n \"operation\": \"smaller\",\n \"value2\": 400\n }]\n }\n }\n },\n {\n \"name\": \"Calculate Wait Time\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const attempt = $json.attempt + 1;\\nconst baseDelay = $json.baseDelay;\\nconst maxAttempts = $json.maxAttempts;\\n\\nif (attempt >= maxAttempts) {\\n throw new Error('Max retry attempts reached');\\n}\\n\\n// Calculate exponential delay with jitter\\nconst exponentialDelay = baseDelay * Math.pow(2, attempt);\\nconst jitter = Math.random() * 1000;\\nconst waitTime = Math.min(exponentialDelay + jitter, 32000);\\n\\nreturn { attempt, waitTime, shouldRetry: true };\"\n }\n },\n {\n \"name\": \"Wait\",\n \"type\": \"n8n-nodes-base.wait\",\n \"parameters\": {\n \"amount\": \"={{ $json.waitTime }}\",\n \"unit\": \"milliseconds\"\n }\n }\n ]\n}\n```\n\n### Method 3: Error Trigger Pattern\n\n```json\n{\n \"nodes\": [\n {\n \"name\": \"Error Trigger\",\n \"type\": \"n8n-nodes-base.errorTrigger\"\n },\n {\n \"name\": \"Analyze Error\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const error = $json.execution.error;\\nconst isRetryable = [429, 503, 502, 504].includes(error.httpCode);\\nconst isRateLimit = error.httpCode === 429;\\n\\nlet retryAfter = 60; // default\\nif (error.headers && error.headers['retry-after']) {\\n retryAfter = parseInt(error.headers['retry-after']) || 60;\\n}\\n\\nreturn { isRetryable, isRateLimit, retryAfter };\"\n }\n },\n {\n \"name\": \"Should Retry?\",\n \"type\": \"n8n-nodes-base.if\",\n \"parameters\": {\n \"conditions\": {\n \"boolean\": [{\n \"value1\": \"={{ $json.isRetryable }}\",\n \"value2\": true\n }]\n }\n }\n },\n {\n \"name\": \"Queue for Retry\",\n \"type\": \"n8n-nodes-base.redis\",\n \"parameters\": {\n \"operation\": \"push\",\n \"key\": \"retry_queue\",\n \"data\": \"={{ JSON.stringify($json.originalPayload) }}\"\n }\n }\n ]\n}\n```\n\n## Best Practices\n\n1. **Set Maximum Retries**: Prevent infinite loops (typically 3-5)\n2. **Add Jitter**: Prevent thundering herd problem\n3. **Cap Maximum Delay**: Usually 30-60 seconds\n4. **Log All Retries**: For debugging and monitoring\n5. **Use Circuit Breaker**: Stop retrying after persistent failures\n\n## HTTP Status Code Handling\n\n| Code | Meaning | Should Retry? | Strategy |\n|------|---------|---------------|----------|\n| 429 | Too Many Requests | Yes | Use Retry-After header |\n| 500 | Server Error | Yes | Exponential backoff |\n| 502 | Bad Gateway | Yes | Short delay, then retry |\n| 503 | Service Unavailable | Yes | Exponential backoff |\n| 504 | Gateway Timeout | Yes | Increase timeout, retry |\n| 400 | Bad Request | No | Fix request data |\n| 401 | Unauthorized | No | Refresh credentials |\n| 403 | Forbidden | No | Check permissions |\n| 404 | Not Found | No | Verify URL/resource |", "metadata": {"topic": "error_handling", "type": "best_practice", "priority": "high"}} | |
| {"instruction": "How do I implement GDPR-compliant data handling in n8n workflows?", "input": "", "output": "# GDPR-Compliant n8n Workflows\n\nEnsure your n8n workflows handle personal data in compliance with GDPR regulations.\n\n## GDPR Core Principles for Workflows\n\n1. **Lawful Basis**: Document why you're processing data\n2. **Data Minimization**: Only collect necessary data\n3. **Purpose Limitation**: Use data only for stated purposes\n4. **Storage Limitation**: Delete data when no longer needed\n5. **Integrity & Confidentiality**: Secure data in transit and at rest\n\n## Data Subject Rights Workflow\n\n```json\n{\n \"name\": \"GDPR Data Subject Request Handler\",\n \"nodes\": [\n {\n \"name\": \"Request Webhook\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"parameters\": {\n \"path\": \"gdpr/request\",\n \"httpMethod\": \"POST\"\n }\n },\n {\n \"name\": \"Validate Request\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const request = $json.body;\\nconst validTypes = ['access', 'rectification', 'erasure', 'portability', 'restriction'];\\n\\nif (!validTypes.includes(request.type)) {\\n throw new Error('Invalid request type');\\n}\\n\\nif (!request.email || !request.verification_token) {\\n throw new Error('Missing required fields');\\n}\\n\\nreturn { ...request, validated: true, timestamp: new Date().toISOString() };\"\n }\n },\n {\n \"name\": \"Route by Type\",\n \"type\": \"n8n-nodes-base.switch\",\n \"parameters\": {\n \"expression\": \"={{ $json.type }}\"\n }\n },\n {\n \"name\": \"Handle Access Request\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"// Collect all data for this user\\nconst email = $json.email;\\n// Query all relevant tables/systems\\nreturn { action: 'compile_data_export', email };\"\n }\n },\n {\n \"name\": \"Handle Erasure Request\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"// Mark for deletion (with 30-day retention for legal holds)\\nreturn {\\n action: 'schedule_deletion',\\n email: $json.email,\\n scheduled_date: new Date(Date.now() + 30*24*60*60*1000).toISOString(),\\n systems: ['crm', 'email', 'analytics']\\n};\"\n }\n },\n {\n \"name\": \"Log Request\",\n \"type\": \"n8n-nodes-base.supabase\",\n \"parameters\": {\n \"operation\": \"insert\",\n \"table\": \"gdpr_requests\",\n \"data\": {\n \"email\": \"={{ $json.email }}\",\n \"type\": \"={{ $json.type }}\",\n \"status\": \"processing\",\n \"created_at\": \"={{ $now.toISO() }}\"\n }\n }\n }\n ]\n}\n```\n\n## Consent Management\n\n```json\n{\n \"name\": \"Consent Tracking\",\n \"nodes\": [\n {\n \"name\": \"Consent Form Webhook\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"parameters\": {\"path\": \"consent\"}\n },\n {\n \"name\": \"Store Consent\",\n \"type\": \"n8n-nodes-base.supabase\",\n \"parameters\": {\n \"operation\": \"upsert\",\n \"table\": \"consents\",\n \"data\": {\n \"email\": \"={{ $json.email }}\",\n \"marketing_consent\": \"={{ $json.marketing }}\",\n \"analytics_consent\": \"={{ $json.analytics }}\",\n \"consent_version\": \"v2.1\",\n \"ip_address\": \"={{ $json.ip }}\",\n \"consent_date\": \"={{ $now.toISO() }}\"\n }\n }\n }\n ]\n}\n```\n\n## Data Anonymization Pattern\n\n```javascript\n// Anonymize PII before analytics processing\nfunction anonymize(data) {\n return {\n ...data,\n email: hashEmail(data.email), // One-way hash\n name: null,\n phone: null,\n ip: data.ip.replace(/\\.\\d+$/, '.0'), // Partial IP\n user_id: generatePseudonymousId(data.user_id)\n };\n}\n```\n\n## Required Documentation\n\n- [ ] Data Processing Register\n- [ ] Privacy Impact Assessment\n- [ ] Consent Records\n- [ ] Data Retention Schedule\n- [ ] Breach Response Plan", "metadata": {"topic": "gdpr_compliance", "type": "guide", "priority": "high"}} | |
| {"instruction": "How do I securely manage API keys and secrets in n8n?", "input": "", "output": "# Secret Management Best Practices in n8n\n\nSecure handling of API keys, credentials, and sensitive data in n8n workflows.\n\n## n8n Built-in Credential Management\n\n### Creating Secure Credentials\n\n1. Navigate to **Settings \u2192 Credentials**\n2. Click **Add Credential**\n3. Select the service type\n4. Enter credentials (stored encrypted at rest)\n\n### Credential Encryption\n\nn8n encrypts credentials using:\n- AES-256-GCM encryption\n- Per-instance encryption key (`N8N_ENCRYPTION_KEY`)\n\n**Set strong encryption key**:\n```bash\nexport N8N_ENCRYPTION_KEY=$(openssl rand -base64 32)\n```\n\n## External Secret Management\n\n### HashiCorp Vault Integration\n\n```json\n{\n \"name\": \"Fetch Secret from Vault\",\n \"nodes\": [\n {\n \"name\": \"Get Vault Token\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://vault.example.com/v1/auth/token/lookup-self\",\n \"headers\": {\n \"X-Vault-Token\": \"{{ $env.VAULT_TOKEN }}\"\n }\n }\n },\n {\n \"name\": \"Fetch Secret\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://vault.example.com/v1/secret/data/api-keys\",\n \"headers\": {\n \"X-Vault-Token\": \"{{ $env.VAULT_TOKEN }}\"\n }\n }\n },\n {\n \"name\": \"Use Secret\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://api.service.com/data\",\n \"headers\": {\n \"Authorization\": \"Bearer {{ $json.data.data.api_key }}\"\n }\n }\n }\n ]\n}\n```\n\n### AWS Secrets Manager\n\n```json\n{\n \"name\": \"AWS Secrets Manager\",\n \"type\": \"n8n-nodes-base.awsSecretsManager\",\n \"parameters\": {\n \"operation\": \"get\",\n \"secretId\": \"prod/api/stripe\"\n }\n}\n```\n\n## Environment Variable Best Practices\n\n```bash\n# .env file (never commit to git!)\nN8N_ENCRYPTION_KEY=your-secure-key\nSTRIPE_SECRET_KEY=sk_live_xxx\nDATABASE_URL=postgres://user:pass@host/db\n\n# Use in workflows\n{{ $env.STRIPE_SECRET_KEY }}\n```\n\n## Security Checklist\n\n- [ ] Use n8n's credential system (never hardcode)\n- [ ] Set strong `N8N_ENCRYPTION_KEY`\n- [ ] Use environment variables for deployment secrets\n- [ ] Rotate credentials regularly\n- [ ] Audit credential access\n- [ ] Use least-privilege access\n- [ ] Enable audit logging\n- [ ] Use HTTPS exclusively\n\n## Credential Rotation Workflow\n\n```json\n{\n \"name\": \"API Key Rotation\",\n \"nodes\": [\n {\n \"name\": \"Schedule - Weekly\",\n \"type\": \"n8n-nodes-base.scheduleTrigger\",\n \"parameters\": {\"rule\": {\"interval\": [{\"field\": \"weeks\", \"weeks\": 1}]}}\n },\n {\n \"name\": \"Generate New Key\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"{{ $env.API_PROVIDER }}/keys\",\n \"method\": \"POST\"\n }\n },\n {\n \"name\": \"Update Vault\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://vault.example.com/v1/secret/data/api-keys\",\n \"method\": \"POST\",\n \"body\": {\"data\": {\"api_key\": \"={{ $json.new_key }}\"}}\n }\n },\n {\n \"name\": \"Revoke Old Key\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"{{ $env.API_PROVIDER }}/keys/{{ $json.old_key_id }}\",\n \"method\": \"DELETE\"\n }\n }\n ]\n}\n```", "metadata": {"topic": "secret_management", "type": "best_practice", "priority": "high"}} | |
| {"instruction": "How do I implement caching in n8n workflows?", "input": "", "output": "# Caching Strategies in n8n Workflows\n\nReduce API calls, improve performance, and lower costs with effective caching.\n\n## Redis-Based Caching\n\n```json\n{\n \"name\": \"Cached API Request\",\n \"nodes\": [\n {\n \"name\": \"Check Cache\",\n \"type\": \"n8n-nodes-base.redis\",\n \"parameters\": {\n \"operation\": \"get\",\n \"key\": \"cache:api:{{ $json.endpoint }}\"\n }\n },\n {\n \"name\": \"Cache Hit?\",\n \"type\": \"n8n-nodes-base.if\",\n \"parameters\": {\n \"conditions\": {\n \"string\": [{\n \"value1\": \"={{ $json.value }}\",\n \"operation\": \"isNotEmpty\"\n }]\n }\n }\n },\n {\n \"name\": \"Return Cached\",\n \"type\": \"n8n-nodes-base.set\",\n \"parameters\": {\n \"values\": {\"string\": [{\"name\": \"data\", \"value\": \"={{ JSON.parse($json.value) }}\"}]}\n }\n },\n {\n \"name\": \"Fetch Fresh\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://api.example.com/{{ $json.endpoint }}\"\n }\n },\n {\n \"name\": \"Store in Cache\",\n \"type\": \"n8n-nodes-base.redis\",\n \"parameters\": {\n \"operation\": \"set\",\n \"key\": \"cache:api:{{ $json.endpoint }}\",\n \"value\": \"={{ JSON.stringify($json.data) }}\",\n \"expire\": true,\n \"ttl\": 3600\n }\n }\n ]\n}\n```\n\n## Supabase-Based Caching\n\n```json\n{\n \"name\": \"Database Cache Layer\",\n \"type\": \"n8n-nodes-base.supabase\",\n \"parameters\": {\n \"operation\": \"upsert\",\n \"table\": \"cache\",\n \"data\": {\n \"cache_key\": \"={{ $json.key }}\",\n \"data\": \"={{ JSON.stringify($json.response) }}\",\n \"expires_at\": \"={{ $now.plus({hours: 1}).toISO() }}\"\n },\n \"onConflict\": \"cache_key\"\n }\n}\n```\n\n## Cache Invalidation Patterns\n\n### Time-Based (TTL)\n```javascript\n// Set expiration when caching\nconst ttl = 3600; // 1 hour\nawait redis.set(key, value, 'EX', ttl);\n```\n\n### Event-Based Invalidation\n```json\n{\n \"name\": \"Invalidate on Update\",\n \"nodes\": [\n {\n \"name\": \"Webhook - Data Updated\",\n \"type\": \"n8n-nodes-base.webhook\"\n },\n {\n \"name\": \"Delete Cache\",\n \"type\": \"n8n-nodes-base.redis\",\n \"parameters\": {\n \"operation\": \"delete\",\n \"key\": \"cache:{{ $json.entity }}:*\"\n }\n }\n ]\n}\n```\n\n## Caching Best Practices\n\n| Data Type | TTL | Strategy |\n|-----------|-----|----------|\n| Static data | 24h | Long cache |\n| User profiles | 1h | Medium + invalidation |\n| Real-time data | Never | Don't cache |\n| API responses | 5-15min | Short cache |\n| Expensive queries | 1h | Warm on write |", "metadata": {"topic": "caching", "type": "best_practice", "priority": "high"}} | |
| {"instruction": "How do I implement batch processing for large datasets in n8n?", "input": "", "output": "# Batch Processing for Large Datasets in n8n\n\nProcess thousands of items efficiently without memory issues or timeouts.\n\n## Split in Batches Node\n\n```json\n{\n \"name\": \"Batch Processor\",\n \"nodes\": [\n {\n \"name\": \"Get All Items\",\n \"type\": \"n8n-nodes-base.supabase\",\n \"parameters\": {\n \"operation\": \"select\",\n \"table\": \"items\",\n \"returnAll\": true\n }\n },\n {\n \"name\": \"Split Batches\",\n \"type\": \"n8n-nodes-base.splitInBatches\",\n \"parameters\": {\n \"batchSize\": 50,\n \"options\": {}\n }\n },\n {\n \"name\": \"Process Batch\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://api.example.com/bulk\",\n \"method\": \"POST\",\n \"body\": \"={{ $json }}\"\n }\n },\n {\n \"name\": \"Rate Limit Wait\",\n \"type\": \"n8n-nodes-base.wait\",\n \"parameters\": {\n \"amount\": 1,\n \"unit\": \"seconds\"\n }\n },\n {\n \"name\": \"Loop Back\",\n \"type\": \"n8n-nodes-base.noOp\"\n }\n ],\n \"connections\": {\n \"Split Batches\": {\n \"main\": [\n [{\"node\": \"Process Batch\", \"type\": \"main\", \"index\": 0}],\n [{\"node\": \"Complete\", \"type\": \"main\", \"index\": 0}]\n ]\n },\n \"Rate Limit Wait\": {\n \"main\": [[{\"node\": \"Split Batches\", \"type\": \"main\", \"index\": 0}]]\n }\n }\n}\n```\n\n## Memory-Efficient Streaming\n\n```json\n{\n \"name\": \"Stream Large File\",\n \"nodes\": [\n {\n \"name\": \"Read File in Chunks\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"const fs = require('fs');\\nconst readline = require('readline');\\n\\nconst stream = fs.createReadStream('/path/to/large-file.csv');\\nconst rl = readline.createInterface({input: stream});\\n\\nconst batch = [];\\nlet batchNum = 0;\\n\\nfor await (const line of rl) {\\n batch.push(parseCsvLine(line));\\n if (batch.length >= 100) {\\n // Process batch\\n await processBatch(batch);\\n batch.length = 0;\\n }\\n}\"\n }\n }\n ]\n}\n```\n\n## Pagination Pattern\n\n```json\n{\n \"name\": \"Paginated API Fetch\",\n \"nodes\": [\n {\n \"name\": \"Initialize\",\n \"type\": \"n8n-nodes-base.set\",\n \"parameters\": {\n \"values\": {\n \"number\": [\n {\"name\": \"page\", \"value\": 1},\n {\"name\": \"pageSize\", \"value\": 100}\n ],\n \"boolean\": [{\"name\": \"hasMore\", \"value\": true}]\n }\n }\n },\n {\n \"name\": \"Fetch Page\",\n \"type\": \"n8n-nodes-base.httpRequest\",\n \"parameters\": {\n \"url\": \"https://api.example.com/items?page={{ $json.page }}&limit={{ $json.pageSize }}\"\n }\n },\n {\n \"name\": \"Check More Pages\",\n \"type\": \"n8n-nodes-base.if\",\n \"parameters\": {\n \"conditions\": {\n \"number\": [{\n \"value1\": \"={{ $json.items.length }}\",\n \"operation\": \"equal\",\n \"value2\": \"={{ $json.pageSize }}\"\n }]\n }\n }\n },\n {\n \"name\": \"Increment Page\",\n \"type\": \"n8n-nodes-base.code\",\n \"parameters\": {\n \"jsCode\": \"return { page: $json.page + 1, pageSize: $json.pageSize };\"\n }\n }\n ]\n}\n```\n\n## Batch Processing Metrics\n\n| Batch Size | Memory Usage | Speed | Use Case |\n|------------|--------------|-------|----------|\n| 10 | Low | Slow | API rate limits |\n| 50 | Medium | Balanced | General processing |\n| 100 | Higher | Fast | Database inserts |\n| 1000 | High | Very fast | Bulk operations |", "metadata": {"topic": "batch_processing", "type": "best_practice", "priority": "high"}} | |