This workflow follows the Error Trigger → HTTP Request 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 →
{
"name": "Social Content Intelligence \u2014 Weekly Report",
"nodes": [
{
"parameters": {
"content": "# Social Content Intelligence \u2014 Weekly Report\n**Version:** 1.0.0 | **Author:** Otter Labs | **Schedule:** Every Monday 9am\n\n## What This Workflow Does\n1. **Collects** your last 30 days of posts from Twitter/X, Instagram, TikTok, LinkedIn, and YouTube in parallel\n2. **Normalizes** all platform data into a unified engagement format\n3. **Analyzes** your top 25 posts with Claude \u2014 extracting hook patterns, winning formats, audience psychology\n4. **Researches** trending topics across Perplexity AI, Reddit, X Trending, TikTok, and Google Trends simultaneously\n5. **Generates** 15 high-potential content ideas tailored to your niche and audience\n6. **Publishes** a complete Weekly Content Intelligence Report to Notion with individual idea sub-pages\n7. **Notifies** you via Slack with a summary and Notion link\n\n## Required Credentials (create these in n8n Credentials first)\n| Service | Type | Auth Detail |\n|---------|------|-------------|\n| Twitter/X | HTTP Header Auth | Bearer Token (requires Elevated Access \u2014 apply at developer.twitter.com) |\n| Instagram | HTTP Header Auth | Graph API long-lived access token (Business/Creator account required) |\n| TikTok | HTTP Header Auth | Bearer token from TikTok Developer Portal |\n| LinkedIn | OAuth2 API | Client ID + Secret, scopes: r_liteprofile r_ugcposts |\n| YouTube | HTTP Query Auth | name=key, API key from Google Cloud Console |\n| Anthropic | HTTP Header Auth | name=x-api-key, value=your API key from console.anthropic.com |\n| Perplexity | HTTP Header Auth | name=Authorization, value=Bearer YOUR_KEY from perplexity.ai/settings |\n| Reddit | HTTP Header Auth | Access token via Reddit OAuth (script app type) |\n| SerpAPI | HTTP Query Auth | name=api_key from serpapi.com |\n| Notion | Notion API | Integration token from notion.so/my-integrations |\n\n## Configuration\nSet all user-specific values in **\u2699\ufe0f Config** node before activating.\nDo NOT hardcode values anywhere else \u2014 everything flows from Config.\n\n## Output Structure\n- **Notion DB:** 1 Weekly Report parent page + 15 individual content idea child pages\n- **Slack:** Success summary with Notion link, or error alert with failure details\n\n",
"height": 1160,
"width": 1172,
"color": 4
},
"id": "c642a6e2-6ff8-4d80-9f40-d568edc34940",
"name": "\ud83d\udccb Documentation",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-2144,
304
]
},
{
"parameters": {
"content": "## Phase 1 \u2014 Social Media Data Collection\nFetches your recent posts from all 5 platforms in parallel. Each fetch node has `continueOnFail: true` \u2014 if one platform API is down or credentials are wrong, the workflow continues with the others rather than crashing. A tag Set node after each fetch stamps `_platform` onto the response so the Transform node knows where each item came from. The Merge node (mode: append) waits for all 5 branches before continuing.",
"height": 200,
"width": 960,
"color": 5
},
"id": "4ff61d41-a618-41d6-9456-9db456f96de1",
"name": "\ud83d\udcca Phase 1: Social Collection",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-384,
-448
]
},
{
"parameters": {
"content": "## Phase 2 \u2014 AI Performance Analysis\nNormalizes all platform data into a unified engagement schema, then selects the top 25 posts by engagement rate. A Code node builds the Claude prompt \u2014 injecting your niche, audience, and all post data. Claude analyzes hook patterns, content formats, winning themes, platform-specific tactics, audience psychology, and content gaps. Response is parsed JSON.",
"height": 200,
"width": 680,
"color": 6
},
"id": "732c8415-546a-461a-9030-715ecf0cc2cd",
"name": "\ud83e\udd16 Phase 2: AI Analysis",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
1168,
-464
]
},
{
"parameters": {
"content": "## Phase 3 \u2014 Trend Research (5 Sources in Parallel)\nRuns simultaneously after the performance analysis completes. **Perplexity** returns AI-synthesized trend narrative. **Reddit** returns the top 15 trending posts across your configured subreddits. **X Trending** returns top trending topics with tweet volume. **TikTok Trends** returns trending hashtags and sounds. **Google Trends** returns search interest timeline for your keywords. All 5 merge before idea generation.",
"height": 200,
"width": 960,
"color": 7
},
"id": "b65c7d7a-5f19-4909-b91a-f05eb0cac313",
"name": "\ud83d\udcc8 Phase 3: Trend Research",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
2016,
-464
]
},
{
"parameters": {
"content": "## Phase 4 \u2014 Notion Publishing\nCreates a parent Weekly Report page in your Notion database (rich blocks: theme, priority ideas, quick wins). Then creates 15 child pages under it \u2014 one per content idea \u2014 each with: hook, sub-hook, angle, full outline, CTA, platform recommendation, effort level, repurpose suggestions, and trending connection. Aggregates results into one summary item, then sends Slack notification.",
"height": 200,
"width": 700,
"color": 3
},
"id": "f69f628c-4d27-4586-a50c-c9ffe7875590",
"name": "\ud83d\udcd3 Phase 4: Notion Output",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
3152,
-448
]
},
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 9 * * 1"
}
]
}
},
"id": "de2731b5-daa4-43df-aff9-0dd5c4c5b052",
"name": "\ud83d\udd50 Weekly Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
-816,
592
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "cfg-01",
"name": "twitterUserId",
"value": "YOUR_TWITTER_USER_ID",
"type": "string"
},
{
"id": "cfg-02",
"name": "instagramUserId",
"value": "YOUR_INSTAGRAM_BUSINESS_USER_ID",
"type": "string"
},
{
"id": "cfg-03",
"name": "linkedinAuthorUrn",
"value": "urn:li:person:YOUR_LINKEDIN_PERSON_ID",
"type": "string"
},
{
"id": "cfg-04",
"name": "youtubeChannelId",
"value": "YOUR_YOUTUBE_CHANNEL_ID",
"type": "string"
},
{
"id": "cfg-05",
"name": "niche",
"value": "entrepreneurship, personal finance, productivity",
"type": "string"
},
{
"id": "cfg-06",
"name": "targetAudience",
"value": "ambitious 25-40 year olds building wealth and businesses online",
"type": "string"
},
{
"id": "cfg-07",
"name": "contentGoal",
"value": "grow social following and drive newsletter signups",
"type": "string"
},
{
"id": "cfg-08",
"name": "redditSubreddits",
"value": "Entrepreneur+startups+personalfinance+productivity+SideProject",
"type": "string"
},
{
"id": "cfg-09",
"name": "googleTrendKeywords",
"value": "entrepreneurship,side hustle,passive income,financial freedom",
"type": "string"
},
{
"id": "cfg-10",
"name": "trendResearchQuery",
"value": "What are the biggest trending topics and conversations happening right now in entrepreneurship, personal finance, and productivity in 2025? Focus on emerging trends, viral discussions, and rising topics.",
"type": "string"
},
{
"id": "cfg-11",
"name": "notionDatabaseId",
"value": "YOUR_NOTION_DATABASE_ID",
"type": "string"
},
{
"id": "cfg-12",
"name": "slackWebhookUrl",
"value": "YOUR_SLACK_WEBHOOK_URL",
"type": "string"
},
{
"id": "cfg-13",
"name": "claudeModel",
"value": "claude-opus-4-6",
"type": "string"
},
{
"id": "cfg-14",
"name": "perplexityModel",
"value": "sonar-pro",
"type": "string"
},
{
"id": "cfg-15",
"name": "postsPerPlatform",
"value": "50",
"type": "string"
},
{
"id": "cfg-16",
"name": "contentIdeasCount",
"value": "15",
"type": "string"
},
{
"id": "cfg-17",
"name": "lookbackDays",
"value": "30",
"type": "string"
},
{
"id": "cfg-18",
"name": "tiktokHashtagsToTrack",
"value": "entrepreneur,sidehustle,passiveincome,personaldevelopment",
"type": "string"
}
]
},
"options": {}
},
"id": "e6b0c0d7-f83b-4500-9b76-ec7e44386c48",
"name": "\u2699\ufe0f Config",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
-576,
592
]
},
{
"parameters": {
"url": "=https://api.twitter.com/2/users/{{ $node['\u2699\ufe0f Config'].json.twitterUserId }}/tweets",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "max_results",
"value": "={{ $node['\u2699\ufe0f Config'].json.postsPerPlatform }}"
},
{
"name": "tweet.fields",
"value": "id,text,created_at,public_metrics,entities,attachments"
},
{
"name": "start_time",
"value": "={{ new Date(Date.now() - parseInt($node['\u2699\ufe0f Config'].json.lookbackDays) * 24 * 60 * 60 * 1000).toISOString() }}"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "f3429a45-f9dc-4f34-a12f-55e7016a8c25",
"name": "\ud83d\udc26 Fetch Twitter Posts",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-96,
-208
],
"continueOnFail": true
},
{
"parameters": {
"url": "=https://graph.instagram.com/{{ $node['\u2699\ufe0f Config'].json.instagramUserId }}/media",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "fields",
"value": "id,caption,media_type,timestamp,like_count,comments_count,permalink,thumbnail_url"
},
{
"name": "limit",
"value": "={{ $node['\u2699\ufe0f Config'].json.postsPerPlatform }}"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "0604aa86-3af1-48fb-8b05-2d4d049c2201",
"name": "\ud83d\udcf8 Fetch Instagram Media",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-96,
192
],
"continueOnFail": true
},
{
"parameters": {
"method": "POST",
"url": "https://open.tiktokapis.com/v2/video/list/",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "0c3c7d40-56b2-4b38-a599-e76a02999ebb",
"name": "\ud83c\udfb5 Fetch TikTok Videos",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-96,
592
],
"continueOnFail": true
},
{
"parameters": {
"url": "=https://api.linkedin.com/v2/ugcPosts?q=authors&authors=List({{ $node['\u2699\ufe0f Config'].json.linkedinAuthorUrn }})&count={{ $node['\u2699\ufe0f Config'].json.postsPerPlatform }}&sortBy=CREATED&fields=id,created,specificContent,socialDetail",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "LinkedIn-Version",
"value": "202304"
},
{
"name": "X-Restli-Protocol-Version",
"value": "2.0.0"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "17d14fac-a58e-450e-8efc-0ffabc92d8fe",
"name": "\ud83d\udcbc Fetch LinkedIn Posts",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-96,
992
],
"continueOnFail": true
},
{
"parameters": {
"url": "https://www.googleapis.com/youtube/v3/search",
"authentication": "genericCredentialType",
"genericAuthType": "httpQueryAuth",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "part",
"value": "snippet,statistics"
},
{
"name": "channelId",
"value": "={{ $node['\u2699\ufe0f Config'].json.youtubeChannelId }}"
},
{
"name": "maxResults",
"value": "50"
},
{
"name": "order",
"value": "date"
},
{
"name": "type",
"value": "video"
},
{
"name": "publishedAfter",
"value": "={{ new Date(Date.now() - parseInt($node['\u2699\ufe0f Config'].json.lookbackDays) * 24 * 60 * 60 * 1000).toISOString() }}"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "9896fc28-4349-48b0-949e-b1c55066ce8a",
"name": "\u25b6\ufe0f Fetch YouTube Videos",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-96,
1392
],
"continueOnFail": true
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-tw",
"name": "_platform",
"value": "twitter",
"type": "string"
}
]
},
"options": {}
},
"id": "791c2dc9-4224-4d97-b4e7-e25205810ee8",
"name": "\ud83c\udff7\ufe0f Tag Twitter",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
144,
-208
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-ig",
"name": "_platform",
"value": "instagram",
"type": "string"
}
]
},
"options": {}
},
"id": "dfd2a46f-619b-4729-ae24-e227d901c1f4",
"name": "\ud83c\udff7\ufe0f Tag Instagram",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
144,
192
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-tt",
"name": "_platform",
"value": "tiktok",
"type": "string"
}
]
},
"options": {}
},
"id": "4f8f95ba-4179-45ca-9fe5-6e5ded804baa",
"name": "\ud83c\udff7\ufe0f Tag TikTok",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
144,
592
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-li",
"name": "_platform",
"value": "linkedin",
"type": "string"
}
]
},
"options": {}
},
"id": "ac8d038c-cef2-44f6-ba45-163389b79074",
"name": "\ud83c\udff7\ufe0f Tag LinkedIn",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
144,
992
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-yt",
"name": "_platform",
"value": "youtube",
"type": "string"
}
]
},
"options": {}
},
"id": "3d246de5-5b09-47e6-9229-82e7452d83bd",
"name": "\ud83c\udff7\ufe0f Tag YouTube",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
144,
1392
]
},
{
"parameters": {},
"id": "06c2490a-9ed9-4e3e-b9f7-ba3256b97398",
"name": "\ud83d\udd00 Merge Social Data",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
384,
592
]
},
{
"parameters": {
"jsCode": "// ============================================================\n// Transform & Normalize Social Media Data\n// Converts all platform API responses into a unified format\n// sorted by engagement rate for AI analysis\n// ============================================================\n\nconst allItems = $input.all();\nconst normalizedPosts = [];\n\nfor (const item of allItems) {\n const d = item.json;\n const platform = d._platform;\n if (!platform) continue;\n\n switch (platform) {\n\n case 'twitter': {\n const tweets = d.data || [];\n for (const t of tweets) {\n const m = t.public_metrics || {};\n const interactions = (m.like_count || 0) + (m.reply_count || 0) + (m.retweet_count || 0) + (m.quote_count || 0);\n const impressions = Math.max(m.impression_count || 0, 1);\n normalizedPosts.push({\n platform: 'twitter',\n id: t.id,\n content: t.text || '',\n hook: (t.text || '').split('\\n')[0].substring(0, 200),\n created_at: t.created_at,\n likes: m.like_count || 0,\n comments: m.reply_count || 0,\n shares: (m.retweet_count || 0) + (m.quote_count || 0),\n views: m.impression_count || 0,\n engagement_rate: parseFloat(((interactions / impressions) * 100).toFixed(4)),\n url: `https://twitter.com/i/web/status/${t.id}`,\n format: (t.text || '').length > 280 ? 'thread' : 'tweet'\n });\n }\n break;\n }\n\n case 'instagram': {\n const posts = d.data || [];\n for (const p of posts) {\n const likes = p.like_count || 0;\n const comments = p.comments_count || 0;\n // Instagram doesn't always return impressions in basic fields\n // Use a conservative estimate of 10x engagement as a fallback\n const impressions = Math.max(likes * 10 + comments * 5, 1);\n normalizedPosts.push({\n platform: 'instagram',\n id: p.id,\n content: p.caption || '',\n hook: (p.caption || '').split('\\n')[0].substring(0, 200),\n created_at: p.timestamp,\n likes,\n comments,\n shares: 0,\n views: impressions,\n engagement_rate: parseFloat((((likes + comments) / impressions) * 100).toFixed(4)),\n url: p.permalink || '',\n format: p.media_type === 'VIDEO' ? 'reel'\n : p.media_type === 'CAROUSEL_ALBUM' ? 'carousel'\n : 'image'\n });\n }\n break;\n }\n\n case 'tiktok': {\n const videos = (d.data && d.data.videos) ? d.data.videos : (d.data || []);\n for (const v of videos) {\n const likes = v.like_count || 0;\n const comments = v.comment_count || 0;\n const shares = v.share_count || 0;\n const views = Math.max(v.view_count || 0, 1);\n normalizedPosts.push({\n platform: 'tiktok',\n id: v.id,\n content: v.video_description || v.title || '',\n hook: (v.video_description || v.title || '').split('\\n')[0].substring(0, 200),\n created_at: new Date((v.create_time || 0) * 1000).toISOString(),\n likes,\n comments,\n shares,\n views,\n engagement_rate: parseFloat((((likes + comments + shares) / views) * 100).toFixed(4)),\n url: v.share_url || '',\n format: 'video'\n });\n }\n break;\n }\n\n case 'linkedin': {\n const posts = d.elements || [];\n for (const p of posts) {\n const shareContent = p.specificContent?.['com.linkedin.ugc.ShareContent'] || {};\n const body = shareContent.shareCommentary?.text || '';\n const stats = p.socialDetail?.totalSocialActivityCounts || {};\n const likes = stats.numLikes || 0;\n const comments = stats.numComments || 0;\n const impressions = Math.max(stats.numImpressions || 0, 1);\n normalizedPosts.push({\n platform: 'linkedin',\n id: p.id,\n content: body,\n hook: body.split('\\n')[0].substring(0, 200),\n created_at: new Date(p.created?.time || 0).toISOString(),\n likes,\n comments,\n shares: stats.numShares || 0,\n views: impressions,\n engagement_rate: parseFloat((((likes + comments) / impressions) * 100).toFixed(4)),\n url: `https://www.linkedin.com/feed/update/${p.id}`,\n format: shareContent.shareMediaCategory === 'VIDEO' ? 'video'\n : shareContent.shareMediaCategory === 'IMAGE' ? 'image'\n : 'post'\n });\n }\n break;\n }\n\n case 'youtube': {\n const videos = d.items || [];\n for (const v of videos) {\n const stats = v.statistics || {};\n const likes = parseInt(stats.likeCount || 0);\n const comments = parseInt(stats.commentCount || 0);\n const views = Math.max(parseInt(stats.viewCount || 0), 1);\n const title = v.snippet?.title || '';\n const description = (v.snippet?.description || '').substring(0, 500);\n normalizedPosts.push({\n platform: 'youtube',\n id: v.id?.videoId || (typeof v.id === 'string' ? v.id : ''),\n content: `${title}\\n\\n${description}`,\n hook: title,\n created_at: v.snippet?.publishedAt,\n likes,\n comments,\n shares: 0,\n views,\n engagement_rate: parseFloat((((likes + comments) / views) * 100).toFixed(4)),\n url: `https://youtube.com/watch?v=${v.id?.videoId || v.id}`,\n format: 'video'\n });\n }\n break;\n }\n }\n}\n\n// Sort by engagement rate descending \u2014 top performers first\nnormalizedPosts.sort((a, b) => b.engagement_rate - a.engagement_rate);\n\n// Build platform breakdown summary\nconst platformCounts = normalizedPosts.reduce((acc, p) => {\n acc[p.platform] = (acc[p.platform] || 0) + 1;\n return acc;\n}, {});\n\n// Select top 25 for AI analysis (keeps Claude prompt lean)\nconst top25 = normalizedPosts.slice(0, 25);\n\nconsole.log(`Normalized ${normalizedPosts.length} posts across ${Object.keys(platformCounts).length} platforms`);\n\nreturn [{\n json: {\n posts: normalizedPosts,\n top25,\n total: normalizedPosts.length,\n platformCounts,\n generatedAt: new Date().toISOString()\n }\n}];"
},
"id": "e354d957-35d6-4b54-afdc-7b050dfbcfbc",
"name": "\ud83d\udd04 Transform & Normalize",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
624,
592
]
},
{
"parameters": {
"jsCode": "// Build the Anthropic API request body for performance analysis.\n// Sends top 25 posts + creator context to Claude for deep pattern extraction.\n\nconst data = $input.first().json;\nconst cfg = $('\u2699\ufe0f Config').first().json;\nconst top25 = data.top25 || [];\n\n// Slim the post data to just what the model needs (saves tokens)\nconst postsForAnalysis = top25.map(p => ({\n platform: p.platform,\n hook: p.hook,\n format: p.format,\n engagement_rate_pct: p.engagement_rate,\n likes: p.likes,\n comments: p.comments,\n shares: p.shares,\n views: p.views\n}));\n\nconst prompt = `You are a world-class content strategist and copywriter who specializes in viral social media growth.\n\nCREATOR CONTEXT\n- Niche: ${cfg.niche}\n- Target Audience: ${cfg.targetAudience}\n- Primary Goal: ${cfg.contentGoal}\n- Total Posts Analyzed: ${data.total}\n- Platform Breakdown: ${JSON.stringify(data.platformCounts)}\n\nTOP ${top25.length} POSTS BY ENGAGEMENT RATE:\n${JSON.stringify(postsForAnalysis, null, 2)}\n\nAnalyze these posts and return a JSON object with EXACTLY this structure. Be specific and data-driven \u2014 cite actual hooks and patterns from the data:\n\n{\n \"top_hook_patterns\": [\n {\n \"pattern_name\": \"e.g. The Uncomfortable Truth\",\n \"description\": \"psychological reason this stops the scroll\",\n \"example_hooks\": [\"exact hook 1 from the data\", \"exact hook 2\"],\n \"avg_engagement_rate\": 0.00,\n \"best_platform\": \"platform name\",\n \"use_when\": \"specific trigger for using this hook\"\n }\n ],\n \"top_content_formats\": [\n {\n \"format\": \"thread|carousel|reel|video|post|tweet\",\n \"why_it_works\": \"mechanism of engagement\",\n \"best_example_hook\": \"top hook using this format\",\n \"avg_engagement_rate\": 0.00,\n \"ideal_length\": \"e.g. 5-7 bullet points, 60-90 second video\"\n }\n ],\n \"winning_themes\": [\n {\n \"theme\": \"theme name\",\n \"description\": \"why this resonates with the specific audience\",\n \"post_count\": 0,\n \"avg_engagement_rate\": 0.00\n }\n ],\n \"platform_insights\": {\n \"twitter\": { \"what_works\": \"\", \"hook_style\": \"\", \"optimal_length\": \"\", \"posting_tip\": \"\" },\n \"instagram\": { \"what_works\": \"\", \"hook_style\": \"\", \"optimal_format\": \"\", \"posting_tip\": \"\" },\n \"tiktok\": { \"what_works\": \"\", \"hook_style\": \"\", \"content_style\": \"\", \"posting_tip\": \"\" },\n \"linkedin\": { \"what_works\": \"\", \"hook_style\": \"\", \"tone\": \"\", \"posting_tip\": \"\" },\n \"youtube\": { \"what_works\": \"\", \"title_pattern\": \"\", \"thumbnail_concept\": \"\", \"posting_tip\": \"\" }\n },\n \"audience_insights\": {\n \"pain_points_that_drive_engagement\": [\"string\"],\n \"desires_that_drive_engagement\": [\"string\"],\n \"emotional_triggers\": [\"string\"],\n \"language_patterns\": [\"exact phrases that appear in high-performing hooks\"]\n },\n \"content_gaps\": [\"topics your audience likely wants that your top posts haven't covered\"],\n \"strategic_summary\": \"3-4 sentences: what's working, why, and the single biggest opportunity to improve performance\"\n}\n\nReturn ONLY the JSON object. No markdown fences, no explanation text outside the JSON.`;\n\nreturn [{\n json: {\n model: cfg.claudeModel || 'claude-opus-4-6',\n max_tokens: 4096,\n messages: [{ role: 'user', content: prompt }]\n }\n}];"
},
"id": "3569087d-28c4-4bb8-93ee-84851fe8487f",
"name": "\ud83d\udccb Prepare Analyze Request",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
864,
592
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.anthropic.com/v1/messages",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "anthropic-version",
"value": "2023-06-01"
},
{
"name": "content-type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "3367c0d9-5d0d-4bca-951c-c4f282d97229",
"name": "\ud83e\udd16 Analyze Top Performers",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1104,
592
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.perplexity.ai/chat/completions",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "ae2b3917-c4d6-4d77-a360-6d983dfdd018",
"name": "\ud83d\udd0d Perplexity Research",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1344,
-208
],
"continueOnFail": true
},
{
"parameters": {
"url": "=https://oauth.reddit.com/r/{{ $node['\u2699\ufe0f Config'].json.redditSubreddits }}/hot.json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "limit",
"value": "25"
},
{
"name": "t",
"value": "week"
}
]
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "User-Agent",
"value": "ContentIntelligence/1.0 (by /u/yourusername)"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "c80deb4d-e3e5-45c0-95fc-183dffcb7fef",
"name": "\ud83d\udc7d Reddit Trends",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1344,
192
],
"continueOnFail": true
},
{
"parameters": {
"url": "https://api.twitter.com/2/trends/by/woeid/1",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "a7c66123-372f-4411-a017-54d1a6de1dc5",
"name": "\ud83d\udcc8 Fetch X Trending",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1344,
592
],
"continueOnFail": true
},
{
"parameters": {
"method": "POST",
"url": "https://open.tiktokapis.com/v2/research/hashtag/query/",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "fa7376c8-81f8-45aa-8e77-f7af2608b95c",
"name": "\ud83c\udfb5 TikTok Trend Research",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1344,
992
],
"continueOnFail": true
},
{
"parameters": {
"url": "https://serpapi.com/search.json",
"authentication": "genericCredentialType",
"genericAuthType": "httpQueryAuth",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "engine",
"value": "google_trends"
},
{
"name": "q",
"value": "={{ $node['\u2699\ufe0f Config'].json.googleTrendKeywords }}"
},
{
"name": "data_type",
"value": "TIMESERIES"
},
{
"name": "date",
"value": "today 1-m"
},
{
"name": "geo",
"value": "US"
}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "46d94154-a8c5-4bf1-ad2d-cb51d6e7bdfc",
"name": "\ud83d\udd0e Google Trends via SerpAPI",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1344,
1392
],
"continueOnFail": true
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-px",
"name": "_source",
"value": "perplexity",
"type": "string"
}
]
},
"options": {}
},
"id": "168f9b41-b0f1-4f75-a5ec-c88f4bb23e3f",
"name": "\ud83c\udff7\ufe0f Tag Perplexity",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
1584,
-208
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-rd",
"name": "_source",
"value": "reddit",
"type": "string"
}
]
},
"options": {}
},
"id": "d8352385-ce7a-4b98-9d20-e9e9d8d2795d",
"name": "\ud83c\udff7\ufe0f Tag Reddit",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
1584,
192
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-xt",
"name": "_source",
"value": "x_trending",
"type": "string"
}
]
},
"options": {}
},
"id": "72198938-3c6a-42d7-a791-d43a352a1a68",
"name": "\ud83c\udff7\ufe0f Tag X Trending",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
1584,
592
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-tkt",
"name": "_source",
"value": "tiktok_trends",
"type": "string"
}
]
},
"options": {}
},
"id": "0a8f1f0d-f8d3-4c2c-add5-1bd405020f3d",
"name": "\ud83c\udff7\ufe0f Tag TikTok Trends",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
1584,
992
]
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "tag-gt",
"name": "_source",
"value": "google_trends",
"type": "string"
}
]
},
"options": {}
},
"id": "a7c947ea-5ab9-4e1d-9edc-c7d7abe462f6",
"name": "\ud83c\udff7\ufe0f Tag Google Trends",
"type": "n8n-nodes-base.set",
"typeVersion": 3.3,
"position": [
1584,
1392
]
},
{
"parameters": {},
"id": "0ff8bba7-d1c6-4af4-bcb5-7c7d5484aa40",
"name": "\ud83d\udd00 Merge Trend Research",
"type": "n8n-nodes-base.merge",
"typeVersion": 3,
"position": [
1824,
592
]
},
{
"parameters": {
"jsCode": "// Build the Anthropic API request for content idea generation.\n// Combines performance analysis output + all trend research into one prompt.\n\nconst cfg = $('\u2699\ufe0f Config').first().json;\nconst trendItems = $input.all();\n\n// ---- Parse performance analysis from Claude ----\nlet analysis = {};\ntry {\n const analyzeResponse = $('\ud83e\udd16 Analyze Top Performers').first().json;\n const rawText = analyzeResponse.content?.[0]?.text || '';\n // Try direct parse first, then strip markdown fences if needed\n try {\n analysis = JSON.parse(rawText);\n } catch (e1) {\n const match = rawText.match(/```(?:json)?\\s*([\\s\\S]*?)\\s*```/) || rawText.match(/\\{[\\s\\S]*\\}/);\n analysis = match ? JSON.parse(match[1] || match[0]) : {};\n }\n} catch (e) {\n console.log('Could not parse analysis response, continuing with empty analysis');\n analysis = {};\n}\n\n// ---- Compile trend research from all 5 sources ----\nconst trends = {};\nfor (const item of trendItems) {\n const d = item.json;\n switch (d._source) {\n case 'perplexity':\n trends.perplexity = d.choices?.[0]?.message?.content || '';\n break;\n case 'reddit':\n trends.reddit_hot = (d.data?.children || []).slice(0, 15).map(p => ({\n title: p.data?.title,\n score: p.data?.score,\n subreddit: p.data?.subreddit,\n num_comments: p.data?.num_comments\n }));\n break;\n case 'x_trending':\n trends.x_trending = d.data || [];\n break;\n case 'tiktok_trends':\n trends.tiktok_hashtags = d.data?.hashtags || d;\n break;\n case 'google_trends':\n trends.google_trends = {\n keywords: cfg.googleTrendKeywords,\n timeline: d.interest_over_time?.timeline_data?.slice(-4) || []\n };\n break;\n }\n}\n\nconst prompt = `You are a world-class content strategist. Using our performance data and current trend research, generate exactly ${cfg.contentIdeasCount || 15} high-potential content ideas.\n\nCREATOR CONTEXT\n- Niche: ${cfg.niche}\n- Target Audience: ${cfg.targetAudience}\n- Content Goal: ${cfg.contentGoal}\n\nWHAT WORKS FOR THIS CREATOR (performance analysis)\n${JSON.stringify({\n top_hooks: analysis.top_hook_patterns?.slice(0, 5),\n winning_themes: analysis.winning_themes?.slice(0, 5),\n pain_points: analysis.audience_insights?.pain_points_that_drive_engagement,\n desires: analysis.audience_insights?.desires_that_drive_engagement,\n language_patterns: analysis.audience_insights?.language_patterns,\n content_gaps: analysis.content_gaps,\n summary: analysis.strategic_summary\n}, null, 2)}\n\nCURRENT TREND INTELLIGENCE (this week)\n${JSON.stringify(trends, null, 2)}\n\nGenerate exactly ${cfg.contentIdeasCount || 15} content ideas. For each idea, write the hook as the ACTUAL first sentence/line of the content \u2014 not a description of the hook. Return ONLY this JSON object:\n\n{\n \"weekly_theme\": \"string \u2014 single overarching theme that connects the best ideas this week\",\n \"theme_rationale\": \"string \u2014 why this theme is timely and resonant right now\",\n \"content_ideas\": [\n {\n \"id\": 1,\n \"title\": \"string \u2014 compelling title for the content piece\",\n \"hook\": \"string \u2014 THE ACTUAL FIRST LINE of the content (not a description \u2014 write the real hook)\",\n \"sub_hook\": \"string \u2014 the second sentence that deepens the tension or promise\",\n \"angle\": \"string \u2014 the unique perspective, contrarian take, or unexpected frame\",\n \"format\": \"tweet|thread|carousel|reel|youtube-video|linkedin-post|tiktok-video\",\n \"primary_platform\": \"string\",\n \"secondary_platforms\": [\"string\"],\n \"trending_connection\": \"string \u2014 specific trend/data point from our research this taps into\",\n \"performance_basis\": \"string \u2014 which of our proven patterns this leverages and why it will work\",\n \"outline\": [\"string \u2014 point 1\", \"string \u2014 point 2\", \"string \u2014 point 3\", \"string \u2014 point 4\", \"string \u2014 point 5\"],\n \"cta\": \"string \u2014 exact call-to-action text\",\n \"hook_pattern_used\": \"string \u2014 which top hook pattern from our analysis this uses\",\n \"potential_score\": 8.5,\n \"effort_level\": \"low|medium|high\",\n \"estimated_time_minutes\": 30,\n \"tags\": [\"string\"],\n \"repurpose_ideas\": [\"string \u2014 how to repurpose across other platforms\"]\n }\n ],\n \"priority_ideas\": [1, 3, 7],\n \"quick_wins\": [2, 5],\n \"batch_recording_sets\": [\n {\n \"theme\": \"string \u2014 batch session theme\",\n \"idea_ids\": [1, 4, 8],\n \"rationale\": \"string \u2014 why these work well to record together\"\n }\n ]\n}\n\nReturn ONLY the JSON object. No markdown fences. No text outside the JSON.`;\n\nreturn [{\n json: {\n model: cfg.claudeModel || 'claude-opus-4-6',\n max_tokens: 8192,\n messages: [{ role: 'user', content: prompt }]\n }\n}];"
},
"id": "f42b63cf-e075-4a50-9cec-006a39854e77",
"name": "\ud83d\udccb Prepare Ideas Request",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2064,
592
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.anthropic.com/v1/messages",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "anthropic-version",
"value": "2023-06-01"
},
{
"name": "content-type",
"value": "application/json"
}
]
},
"sendBody": true,
"bodyParameters": {
"parameters": [
{}
]
},
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
}
},
"id": "c0d83749-b2b8-47ac-88a7-7bc9e43e3916",
"name": "\ud83d\udca1 Generate Content Ideas",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
2304,
592
]
},
{
"parameters": {
"jsCode": "// Parse Claude's content ideas response and prepare data for Notion\nconst claudeResponse = $input.first().json;\nconst cfg = $('\u2699\ufe0f Config').first().json;\nconst rawContent = claudeResponse.content?.[0]?.text || '';\n\nlet ideasData = {};\ntry {\n ideasData = JSON.parse(rawContent);\n} catch (e) {\n // Try stripping markdown code fences if present\n const match = rawContent.match(/```(?:json)?\\s*([\\s\\S]*?)\\s*```/) || rawContent.match(/\\{[\\s\\S]*\\}/);\n if (match) {\n try {\n ideasData = JSON.parse(match[1] || match[0]);\n } catch (e2) {\n throw new Error(`Could not parse Claude response as JSON: ${e2.message}\\n\\nRaw response: ${rawContent.substring(0, 500)}`);\n }\n } else {\n throw new Error('No valid JSON found in Claude response');\n }\n}\n\nconst now = new Date();\nconst weekStr = now.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });\nconst ideas = ideasData.content_ideas || [];\n\n// Build platform insights summary from Phase 2 analysis\nlet analysisSummary = 'See analysis output for details.';\ntry {\n const analyzeResponse = $('\ud83e\udd16 Analyze Top Performers').first().json;\n const analysisRaw = analyzeResponse.content?.[0]?.text || '';\n const analysisData = JSON.parse(analysisRaw);\n analysisSummary = analysisData.strategic_summary || analysisSummary;\n} catch (e) {\n // Non-fatal \u2014 use fallback\n}\n\nconsole.log(`Parsed ${ideas.length} content ideas. Weekly theme: ${ideasData.weekly_theme}`);\n\nreturn [{\n json: {\n reportTitle: `\ud83d\udcca Content Intelligence Report \u2014 Week of ${weekStr}`,\n weeklyTheme: ideasData.weekly_theme || 'Content Strategy Week',\n themeRationale: ideasData.theme_rationale || '',\n analysisSummary,\n totalIdeas: ideas.length,\n priorityIdeas: ideasData.priority_ideas || [],\n quickWins: ideasData.quick_wins || [],\n batchSets: ideasData.batch_recording_sets || [],\n generatedAt: now.toISOString(),\n ideas,\n notionDatabaseId: cfg.notionDatabaseId,\n niche: cfg.niche,\n targetAudience: cfg.targetAudience\n }\n}];"
},
"id": "961bbf43-65ac-40cf-8d18-c412a52e0f91",
"name": "\ud83d\udcdd Format Notion Report Data",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
2544,
592
]
},
{
"parameters": {
"pageId": {
"__rl": true,
"mode": "url",
"value": ""
},
"title": "={{ $json.reportTitle }}",
"blockUi": {
"blockValues": [
{
"type": "callout"
},
{
"type": "heading_2",
"textContent": "\ud83d\uddd3\ufe0f Weekly Theme"
},
{
"type": "quote"
},
{
"textContent": "={{ $json.themeRationale }}"
},
{
"type": "heading_2",
"textContent": "\ud83d\udcca Performance Intelligence Summary"
},
{
"textContent": "={{ $json.analysisSummary }}"
},
{
"type": "heading_2",
"textContent": "\u2b50 Priority Ideas This Week"
},
{
"textContent": "={{ `Ideas #${$json.priorityIdeas.join(', #')} \u2014 highest potential based on performance data + trend alignment` }}"
},
{
"type": "heading_2",
"textContent": "\u26a1 Quick Wins (Low Effort, High Impact)"
},
{
"textContent": "={{ `Ideas #${$json.quickWins.join(', #')} \u2014 can be produced and published within 30-60 minutes` }}"
},
{
"type": "heading_2",
"textContent": "\ud83c\udfac Batch Recording Sets"
},
{
"textContent": "={{ $json.batchSets.map(s => `**${s.theme}** (Ideas ${s.idea_ids.join(', ')}): ${s.rationale}`).join('\\n\\n') }}"
},
{
"type": "divider"
},
{
"type": "heading_2",
"textContent": "={{ `\ud83d\udca1 ${$json.totalIdeas} Content Ideas` }}"
},
{
"textContent": "Individual idea pages are linked below. \u2b50 = Priority \u26a1 = Quick Win"
}
]
},
"options": {}
},
"id": "4442e924-e440-4cde-9c9f-1e2961284663",
"name": "\ud83d\udcd3 Create Notion Report Page",
"type": "n8n-nodes-base.notion",
"typeVersion": 2.2,
"position": [
2784,
592
]
},
{
"parameters": {
"jsCode": "// Split the ideas array into individual items.\n// n8n will run the downstream Notion node once per item,\n// creating one child page per content idea.\n\nconst reportData = $('\ud83d\udcdd Format Notion Report Data').first().json;\nconst notionResult = $input.first().json;\n\n// The Notion API returns the created page's ID \u2014 we need this as the parent\nconst parentPageId = notionResult.id || '';\n\nif (!parentPageId) {\n throw new Error('No parent page ID returned from Notion. Check Notion credentials and database ID.');\n}\n\nconst ideas = reportData.ideas || [];\nconst priorityIds = reportData.priorityIdeas || [];\nconst quickWinIds = reportData.quickWins || [];\n\nconsole.log(`Creating ${ideas.length} idea pages as children of page ${parentPageId}`);\n\n// Return one item per idea \u2014 each becomes one Notion child page\nreturn ideas.map(idea => ({\n json: {\n parentPageId,\n ...idea,\n isPriority: priorityIds.includes(idea.id),\n isQuickWin: quickWinIds.includes(idea.id),\n weeklyTheme: reportData.weeklyTheme,\n niche: reportData.niche\n }\n}));"
},
"id": "d0689e13-3895-44b5-ad7b-2126fd05c2a4",
"name": "\ud83d\uddc2\ufe0f Prepare Idea Items",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
3024,
592
]
},
{
"parameters": {
"pageId": "={{ $json.parentPageId }}",
"title": "={{ `${$json.isPriority ? '\u2b50 ' : ''}${$json.isQuickWin ? '\u26a1 ' : ''}#${$json.id} \u2014 ${$json.title}` }}",
"blockUi": {
"blockValues": [
{
"type": "callout"
},
{
"type": "quote"
},
{
"type": "heading_3",
"textContent": "\ud83d\udcd0 Angle"
},
{
"textContent": "={{ $json.angle }}"
},
{
"type": "heading_3",
"textContent": "\ud83d\udccb Outline"
},
{
"type": "bulleted_list_item",
"textContent": "={{ $json.outline[0] || '' }}"
},
{
"type": "bulleted_list_item",
"textContent": "={{ $json.outline[1] || '' }}"
},
{
"type": "bulleted_list_item",
"textContent": "={{ $json.outline[2] || '' }}"
},
{
"type": "bulleted_list_item",
"textContent": "={{ $json.outline[3] || '' }}"
},
{
"type": "bulleted_list_item",
"textContent": "={{ $json.outline[4] || '' }}"
},
{
"type": "heading_3",
"textContent": "\ud83d\udd27 Production Details"
},
{
"textContent": "={{ `\ud83d\udce3 CTA: ${$json.cta}` }}"
},
{
"textContent": "={{ `\ud83c\udfaf Primary Platform: ${$json.primary_platform} | Format: ${$json.format}` }}"
},
{
"textContent": "={{ `\ud83d\udd01 Also Post On: ${($json.secondary_platforms || []).join(', ')}` }}"
},
{
"textContent": "={{ `\u23f1 Effort: ${$json.effort_level} | Est. Time: ${$json.estimated_time_minutes} min` }}"
},
{
"textContent": "={{ `\ud83c\udfa3 Hook Pattern: ${$json.hook_pattern_used}` }}"
},
{
"textContent": "={{ `\u2b50 Potential Score: ${$json.potential_score}/10` }}"
},
{
"type": "heading_3",
"textContent": "\ud83d\udcc8 Why This Will Work"
},
{
"textContent": "={{ $json.performance_basis }}"
},
{
"textContent": "={{ `\ud83d\udd25 Trending Connection: ${$json.trending_connection}` }}"
},
{
"type": "heading_3",
"textContent": "\u267b\ufe0f Repurpose Ideas"
},
{
"textContent": "={{ ($json.repurpose_ideas || []).join('\\n\u2022 ') }}"
},
{
"type": "heading_3",
"textContent": "\ud83c\udff7\ufe0f Tags"
},
{
"textContent": "={{ ($json.tags || []).map(t => `#${t}`).join(' ') }}"
}
]
},
"options": {}
},
"id": "3d25716c-4d83-4691-957a-b239cfc75c93",
"name": "\ud83d\udcc4 Create Notion Idea Page",
"type": "n8n-nodes-base.notion",
"typeVersion": 2.2,
"position": [
3264,
592
]
},
{
"parameters": {
"jsCode": "// Collapse N idea-creation results (one per idea) back into\n// a single summary item for the Slack notification.\n\nconst items = $input.all();\nconst cfg = $('\u2699\ufe0f Config').first().json;\nconst reportData = $('\ud83d\udcdd Format Notion Report Data').first().json;\nconst parentPage = $('\ud83d\udcd3 Create Notion Report Page').first().json;\n\nconst successfulPages = items.filter(i => i.json.object === 'page' || i.json.id);\nconst notionUrl = parentPage.url || `https://notion.so/${(parentPage.id || '').replace(/-/g, '')}`;\n\nconsole.log(`Successfully created ${successfulPages.length}/${items.length} idea pages`);\n\nreturn [{\n json: {\n success: true,\n reportTitle: reportData.reportTitle,\n weeklyTheme: reportData.weeklyTheme,\n ideasCreated: successfulPages.length,\n ideasRequested: items.length,\n notionUrl,\n generatedAt: new Date().toISOString(),\n slackMessage: `*\u2705 Weekly Content Intelligence Report Ready*\\n\\n*Theme:* ${reportData.weeklyTheme}\\n*Ideas Created:* ${successfulPages.length}/${items.length}\\n*Notion Report:* ${notionUrl}\\n\\n_Generated ${new Date().toLocaleString()}_`\n }\n}];"
},
"id": "181b2260-594b-4bc9-8097-b304392ac555",
"name": "\ud83d\udcca Aggregate Results",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
3504,
592
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $node['\u2699\ufe0f Config'].json.slackWebhookUrl }}",
"sendBody": true,
"bodyParameters": {
"parameters": [
{}
]
},
"options": {}
},
"id": "1efe4f57-fce9-4d98-9920-6940f4588716",
"name": "\u2705 Success Notification",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
3744,
592
]
},
{
"parameters": {},
"id": "c9b08620-62a0-4a53-9f87-fefee9159483",
"name": "\ud83d\udea8 Error Trigger",
"type": "n8n-nodes-base.errorTrigger",
"typeVersion": 1,
"position": [
-816,
1200
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $node['\u2699\ufe0f Config'].json.slackWebhookUrl }}",
"sendBody": true,
"bodyParameters": {
"parameters": [
{}
]
},
"options": {}
},
"id": "ce7ad89b-074f-4356-a255-2575b2da75c7",
"name": "\ud83d\udd34 Send Error Alert",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-576,
1200
]
}
],
"connections": {
"\ud83d\udd50 Weekly Trigger": {
"main": [
[
{
"node": "\u2699\ufe0f Config",
"type": "main",
"index": 0
}
]
]
},
"\u2699\ufe0f Config": {
"main": [
[
{
"node": "\ud83d\udc26 Fetch Twitter Posts",
"type": "main",
"index": 0
},
{
"node": "\ud83d\udcf8 Fetch Instagram Media",
"type": "main",
"index": 0
},
{
"node": "\ud83c\udfb5 Fetch TikTok Videos",
"type": "main",
"index": 0
},
{
"node": "\ud83d\udcbc Fetch LinkedIn Posts",
"type": "main",
"index": 0
},
{
"node": "\u25b6\ufe0f Fetch YouTube Videos",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udc26 Fetch Twitter Posts": {
"main": [
[
{
"node": "\ud83c\udff7\ufe0f Tag Twitter",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udcf8 Fetch Instagram Media": {
"main": [
[
{
"node": "\ud83c\udff7\ufe0f Tag Instagram",
"type": "main",
"index": 0
}
]
]
},
"\ud83c\udfb5 Fetch TikTok Videos": {
"main": [
[
{
"node": "\ud83c\udff7\ufe0f Tag TikTok",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udcbc Fetch LinkedIn Posts": {
"main": [
[
{
"node": "\ud83c\udff7\ufe0f Tag LinkedIn",
"type": "main",
"index": 0
}
]
]
},
"\u25b6\ufe0f Fetch YouTube Videos": {
"main": [
[
{
"node": "\ud83c\udff7\ufe0f Tag YouTube",
"type": "main",
"index": 0
}
]
]
},
"\ud83c\udff7\ufe0f Tag Twitter": {
"main": [
[
{
"node": "\ud83d\udd00 Merge Social Data",
"type": "main",
"index": 0
}
]
]
},
"\ud83c\udff7\ufe0f Tag Instagram": {
"main": [
[
{
"node": "\ud83d\udd00 Merge Social Data",
"type": "main",
"index": 1
}
]
]
},
"\ud83d\udd00 Merge Social Data": {
"main": [
[
{
"node": "\ud83d\udd04 Transform & Normalize",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udd04 Transform & Normalize": {
"main": [
[
{
"node": "\ud83d\udccb Prepare Analyze Request",
"type": "main",
"index": 0
}
]
]
},
"\ud83d\udccb Prepare Analyze Request": {
"main": [
[
{
"node": "\ud83e\udd16 Analyze Top Performers",
"type": "main",
"index": 0
}
]
]
},
"\ud83e\
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Social Content Intelligence — Weekly Report. Uses httpRequest, notion, errorTrigger. Scheduled trigger; 42 nodes.
Source: https://github.com/jslizar/builder-lab/blob/dac901bc94368095e42e48185c9bb3f1c5c8e529/automations/n8n-workflows/social-content-intelligence.json — 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.
Daily Business Report Generator. Uses googleSheets, httpRequest, slack, gmail. Scheduled trigger; 17 nodes.
Security teams, DevOps engineers, vulnerability analysts, and automation builders who want to eliminate repetitive Nessus scan parsing, AI-based risk triage, and manual reporting. Designed for orgs fo
This workflow runs daily at 8 AM to monitor competitors by scraping their homepages and reading company RSS feeds, Google News RSS, and Reddit RSS, then uses OpenAI to generate an intelligence report
This workflow triggers when a HubSpot deal stage changes to Closed Won and automatically generates an invoice. It collects deal and contact data, builds a styled invoice, converts it into a PDF, and s
Automate LinkedIn lead generation from Sales Navigator search to personalized outreach. The Periodix node finds prospects, Claude AI scores each one against your ICP, writes personalized connection re