This workflow corresponds to n8n.io template #14298 โ we link there as the canonical source.
This workflow follows the Datatable โ Gmail 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 โ
{
"nodes": [
{
"id": "8253a240-ad37-4216-863d-3060e87fecae",
"name": "Loop Over Reddit Queries",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1456,
1152
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "2abb82bf-b2bb-4e94-b5c4-055019dc04a9",
"name": "Sort Reddit Posts by Score",
"type": "n8n-nodes-base.code",
"notes": "Sorts posts",
"position": [
1920,
1152
],
"parameters": {
"jsCode": "// Code pour n\u0153ud Code n8n - Classement Reddit avec output simplifi\u00e9\n\n// R\u00e9cup\u00e9rer les donn\u00e9es d'entr\u00e9e\nconst items = $input.all();\n\n// Filtrer uniquement les posts (exclure les commentaires)\nconst posts = items.filter(item => item.json.dataType === 'post');\n\n// Calculer le score pour chaque post\nconst postsWithScore = posts.map(item => {\n const post = item.json;\n \n // Calcul du score : 1 point par upvote + 2 points par commentaire\n const upvoteScore = (post.upVotes || 0) * 1;\n const commentScore = (post.numberOfComments || 0) * 2\n ;\n const totalScore = upvoteScore + commentScore;\n \n return {\n json: {\n url: post.url,\n title: post.title || \"Pas de titre\",\n body: post.body || \"Pas de contenu\",\n score: totalScore,\n // Donn\u00e9es d\u00e9taill\u00e9es pour debug (optionnel)\n details: {\n upvotes: post.upVotes || 0,\n comments: post.numberOfComments || 0,\n community: post.communityName,\n timestamp: post.createdAt\n }\n }\n };\n});\n\n// Trier par score d\u00e9croissant\nconst sortedPosts = postsWithScore.sort((a, b) => b.json.score - a.json.score);\n\n// Prendre les 10 meilleurs\nconst top10Posts = sortedPosts.slice(0, 10);\n\n// Ajouter un rang \u00e0 chaque post\nconst rankedPosts = top10Posts.map((post, index) => ({\n json: {\n rank: index + 1,\n url: post.json.url,\n title: post.json.title,\n body: post.json.body,\n score: post.json.score\n }\n}));\n\n// Log pour debug\nconsole.log(`\ud83c\udfc6 TOP 10 POSTS REDDIT - Score = (upvotes\u00d71) + (commentaires\u00d72)`);\nconsole.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);\n\nrankedPosts.forEach((post, index) => {\n const p = post.json;\n const shortTitle = p.title.length > 60 ? p.title.substring(0, 60) + '...' : p.title;\n const shortBody = p.body.length > 80 ? p.body.substring(0, 80) + '...' : p.body;\n \n console.log(`${p.rank}. Score: ${p.score}`);\n console.log(` URL: ${p.url}`);\n console.log(` Titre: \"${shortTitle}\"`);\n console.log(` Contenu: \"${shortBody}\"`);\n console.log(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);\n});\n\nconsole.log(`\\n\ud83d\udcca Analys\u00e9 ${posts.length} posts au total`);\n\n// Retourner les r\u00e9sultats avec le format demand\u00e9\nreturn rankedPosts;"
},
"notesInFlow": true,
"typeVersion": 2
},
{
"id": "5164bd2a-5164-4e78-86c6-4c8c59cfadd5",
"name": "Reddit Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
976,
1152
],
"parameters": {
"rule": {
"interval": [
{}
]
}
},
"typeVersion": 1.2
},
{
"id": "d15af1fa-c841-4758-8e56-ac08281e101c",
"name": "Get Reddit Query Rows",
"type": "n8n-nodes-base.dataTable",
"position": [
1184,
1152
],
"parameters": {
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "BYMzHVIbNU0mmvAZ",
"cachedResultUrl": "/projects/oTpNUA7ZOCuhiQA0/datatables/BYMzHVIbNU0mmvAZ",
"cachedResultName": "Query social media"
}
},
"typeVersion": 1
},
{
"id": "9000ea56-c59b-44de-93c3-c477013d0369",
"name": "Send Reddit Report Email",
"type": "n8n-nodes-base.gmail",
"notes": "Send dahsboard with top 10 of the most engaging post ",
"position": [
2384,
1152
],
"parameters": {
"sendTo": "user@example.com",
"message": "=<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Trends Social Media - {{ $('Loop Over Reddit Queries').first().json.Query }}</title>\n <style>\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n\n body {\n font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n line-height: 1.6;\n color: #333;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n min-height: 100vh;\n padding: 20px;\n }\n\n .newsletter-container {\n max-width: 1200px;\n margin: 0 auto;\n background: white;\n border-radius: 20px;\n overflow: hidden;\n box-shadow: 0 20px 40px rgba(0,0,0,0.1);\n }\n\n .header {\n background: linear-gradient(135deg, #ff6b6b, #ee5a24);\n color: white;\n padding: 40px 30px;\n text-align: center;\n }\n\n .header h1 {\n font-size: 2.8em;\n margin-bottom: 10px;\n font-weight: 700;\n }\n\n .header p {\n font-size: 1.2em;\n opacity: 0.9;\n margin-bottom: 15px;\n }\n\n .keyword-badge {\n display: inline-block;\n background: rgba(255,255,255,0.2);\n color: white;\n padding: 8px 20px;\n border-radius: 20px;\n font-size: 1em;\n font-weight: 600;\n backdrop-filter: blur(10px);\n }\n\n .stats-overview {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));\n gap: 20px;\n padding: 30px;\n background: #f8f9fa;\n }\n\n .stat-card {\n background: white;\n padding: 20px;\n border-radius: 15px;\n text-align: center;\n box-shadow: 0 5px 15px rgba(0,0,0,0.08);\n border-left: 4px solid;\n }\n\n .stat-card.high { border-left-color: #ff4757; }\n .stat-card.medium { border-left-color: #ffa502; }\n .stat-card.low { border-left-color: #70a1ff; }\n\n .stat-number {\n font-size: 2.5em;\n font-weight: bold;\n margin-bottom: 5px;\n }\n\n .stat-label {\n color: #666;\n font-size: 0.9em;\n text-transform: uppercase;\n letter-spacing: 1px;\n }\n\n .table-container {\n margin: 30px;\n background: white;\n border-radius: 15px;\n overflow: hidden;\n box-shadow: 0 10px 25px rgba(0,0,0,0.1);\n }\n\n .table-header {\n background: linear-gradient(135deg, #2c3e50, #34495e);\n color: white;\n padding: 25px 30px;\n text-align: center;\n }\n\n .table-title {\n font-size: 1.8em;\n font-weight: 600;\n margin-bottom: 5px;\n }\n\n .table-subtitle {\n opacity: 0.8;\n font-size: 1em;\n }\n\n .trends-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.95em;\n }\n\n .trends-table th {\n background: #f8f9fa;\n padding: 15px 12px;\n text-align: left;\n font-weight: 600;\n color: #555;\n border-bottom: 2px solid #dee2e6;\n text-transform: uppercase;\n font-size: 0.8em;\n letter-spacing: 0.5px;\n }\n\n .trends-table td {\n padding: 15px 12px;\n border-bottom: 1px solid #eee;\n vertical-align: middle;\n text-align: center;\n }\n\n .trends-table td:nth-child(3),\n .trends-table td:nth-child(4) {\n text-align: left;\n }\n\n .trends-table tr:nth-child(even) {\n background-color: #f8f9fa;\n }\n\n .trends-table tr:hover {\n background-color: #e3f2fd;\n transform: scale(1.01);\n transition: all 0.2s ease;\n }\n\n .rank-number {\n font-weight: bold;\n font-size: 1.2em;\n color: #2c3e50;\n }\n\n .rank-number.top3 {\n color: #ff6b6b;\n font-size: 1.4em;\n }\n\n .source-badge {\n padding: 6px 12px;\n border-radius: 20px;\n font-size: 0.8em;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .source-badge.tiktok {\n background: #ff0050;\n color: white;\n }\n\n .source-badge.reddit {\n background: #ff4500;\n color: white;\n }\n\n .source-badge.instagram {\n background: #e4405f;\n color: white;\n }\n\n .level-badge {\n padding: 4px 10px;\n border-radius: 15px;\n font-size: 0.75em;\n font-weight: 600;\n text-transform: uppercase;\n }\n\n .level-badge.high {\n background: #ff4757;\n color: white;\n }\n\n .level-badge.medium {\n background: #ffa502;\n color: white;\n }\n\n .level-badge.low {\n background: #70a1ff;\n color: white;\n }\n\n .content-text {\n max-width: 250px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: #555;\n line-height: 1.4;\n }\n\n .author-link {\n color: #667eea;\n text-decoration: none;\n font-weight: 600;\n }\n\n .author-link:hover {\n text-decoration: underline;\n }\n\n .score-number {\n font-weight: bold;\n color: #2c3e50;\n font-size: 1.1em;\n }\n\n .footer {\n text-align: center;\n padding: 30px;\n background: #f8f9fa;\n color: #666;\n border-top: 1px solid #eee;\n }\n\n .footer p {\n margin-bottom: 10px;\n }\n\n .date-info {\n font-size: 0.9em;\n color: #888;\n }\n\n @media (max-width: 768px) {\n .newsletter-container {\n margin: 10px;\n border-radius: 15px;\n }\n \n .header {\n padding: 30px 20px;\n }\n \n .header h1 {\n font-size: 2.2em;\n }\n \n .table-container {\n margin: 20px;\n overflow-x: auto;\n }\n \n .trends-table {\n min-width: 800px;\n }\n \n .stats-overview {\n padding: 20px;\n grid-template-columns: 1fr;\n }\n }\n </style>\n</head>\n<body>\n <div class=\"newsletter-container\">\n <!-- Header -->\n <header class=\"header\">\n <h1>\ud83d\udcca R\u00e9capitulatif par Hashtag</h1>\n <p>Scores totaux par r\u00e9seau social</p>\n </header>\n\n <!-- Hashtag Summary Table -->\n <section class=\"table-container\" style=\"margin: 30px 30px 0 30px;\">\n <table class=\"trends-table\">\n <thead>\n <tr>\n <th>Hashtag</th>\n <th>TikTok</th>\n <th>Reddit</th>\n <th>Instagram</th>\n <th>Score Total</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>\n <span style=\"font-weight: bold; color: #ff6b6b; font-size: 1.1em;\">#{{ $('Loop Over Reddit Queries').first().json.Query }}</span>\n </td>\n <td>\n <span class=\"score-number\">{{ $('Rank Reddit Posts1').all().filter(item => item.json.source === 'TikTok').reduce((sum, item) => sum + item.json.score, 0).toLocaleString('fr-FR') }}</span>\n </td>\n <td>\n <span class=\"score-number\">{{ $('Rank Reddit Posts1').all().filter(item => item.json.source === 'Reddit').reduce((sum, item) => sum + item.json.score, 0).toLocaleString('fr-FR') }}</span>\n </td>\n <td>\n <span class=\"score-number\">{{ $('Rank Reddit Posts1').all().filter(item => item.json.source === 'Instagram').reduce((sum, item) => sum + item.json.score, 0).toLocaleString('fr-FR') }}</span>\n </td>\n <td>\n <span class=\"score-number\" style=\"color: #ff6b6b; font-size: 1.2em;\">{{ $('Rank Reddit Posts1').all().reduce((sum, item) => sum + item.json.score, 0).toLocaleString('fr-FR') }}</span>\n </td>\n </tr>\n </tbody>\n </table>\n </section>\n\n <!-- Main Table -->\n <section class=\"table-container\">\n <div class=\"table-header\">\n <div class=\"table-title\">#{{ $('Loop Over Reddit Queries').first().json.Query }}</div>\n <div class=\"table-subtitle\"></div>\n </div>\n \n <table class=\"trends-table\">\n <thead>\n <tr>\n <th>Rang</th>\n <th>Source</th>\n <th>Auteur</th>\n <th>Contenu</th>\n <th>Score</th>\n <th>Level</th>\n </tr>\n </thead>\n <tbody>\n {{ $('Rank Reddit Posts1').all().map(item => `\n <tr onclick=\"window.open('${item.json.url}', '_blank')\" style=\"cursor: pointer;\">\n <td>\n <span class=\"rank-number ${item.json.rank <= 3 ? 'top3' : ''}\">${item.json.rank}</span>\n </td>\n <td>\n <span class=\"source-badge ${item.json.source.toLowerCase()}\">${item.json.source}</span>\n </td>\n <td>\n <a href=\"${item.json.url}\" target=\"_blank\" class=\"author-link\">${item.json.author}</a>\n </td>\n <td>\n <div class=\"content-text\" title=\"${item.json.content}\">${item.json.content}</div>\n </td>\n <td>\n <span class=\"score-number\">${item.json.score.toLocaleString('fr-FR')}</span>\n </td>\n <td>\n <span class=\"level-badge ${item.json.level.toLowerCase()}\">${item.json.level}</span>\n </td>\n </tr>\n `).join('') }}\n </tbody>\n </table>\n </section>\n\n <!-- Footer -->\n <footer class=\"footer\">\n <p><strong>Social Media Trends Dashboard</strong></p>\n <p>Analyse automatis\u00e9e des contenus par mot-cl\u00e9</p>\n <div class=\"date-info\">\n <p>G\u00e9n\u00e9r\u00e9 le {{ new Date().toLocaleDateString('fr-FR', { \n year: 'numeric', \n month: 'long', \n day: 'numeric', \n hour: '2-digit', \n minute: '2-digit' \n }) }}</p>\n </div>\n </footer>\n </div>\n</body>\n</html>",
"options": {},
"subject": "Social media monitoring"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"executeOnce": true,
"notesInFlow": true,
"typeVersion": 2.1
},
{
"id": "06bb249b-5562-4dd6-a6c3-d4c5229af21a",
"name": "Push Results to Data Table",
"type": "n8n-nodes-base.dataTable",
"position": [
2384,
1024
],
"parameters": {
"columns": {
"value": {
"url": "={{ $json.url }}",
"Date": "={{ $now.toISO() }}",
"rank": "={{ $json.rank }}",
"level": "={{ $json.level }}",
"score": "={{ $json.score }}",
"author": "={{ $json.author }}",
"source": "={{ $json.source }}",
"content": "={{ $json.content }}",
"keyword": "={{ $json.keyword }}"
},
"schema": [
{
"id": "rank",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "rank",
"defaultMatch": false
},
{
"id": "keyword",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "keyword",
"defaultMatch": false
},
{
"id": "source",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "source",
"defaultMatch": false
},
{
"id": "author",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "author",
"defaultMatch": false
},
{
"id": "content",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "content",
"defaultMatch": false
},
{
"id": "score",
"type": "number",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "score",
"defaultMatch": false
},
{
"id": "level",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "level",
"defaultMatch": false
},
{
"id": "url",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "url",
"defaultMatch": false
},
{
"id": "Date",
"type": "dateTime",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "Date",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "75Jvx9ALCoEGcdwY",
"cachedResultUrl": "/projects/oTpNUA7ZOCuhiQA0/datatables/75Jvx9ALCoEGcdwY",
"cachedResultName": "Trend Social media"
}
},
"typeVersion": 1
},
{
"id": "9936958b-5806-4877-9fdb-1577004b1525",
"name": "Sticky Note13",
"type": "n8n-nodes-base.stickyNote",
"position": [
368,
784
],
"parameters": {
"width": 480,
"height": 896,
"content": "## Trend monitoring Reddit\n\n### How it works\n\n1. A schedule trigger fires periodically and retrieves a list of Reddit search queries from a data table.\n2. The workflow loops over each query and sends it to the Apify Reddit scraper API to fetch posts.\n3. Two code nodes sort and rank the scraped Reddit posts based on engagement or relevance.\n4. The ranked results are sent as a Gmail email notification and simultaneously stored back into a data table for record-keeping.\n\n### Setup steps\n\n- - [ ] Configure the **Reddit Schedule Trigger1** with the desired run frequency (e.g. daily, hourly).\n- - [ ] Populate the **Reddit Get row(s)1** data table with the Reddit search queries you want to monitor.\n- - [ ] Add your **Apify API key** to the `Reddit solo get post` HTTP Request node (URL contains the Apify actor endpoint).\n- - [ ] Connect your **Gmail account** credentials to the `Reddit Send a message1` node and set the recipient email address.\n- - [ ] Configure the **Reddot Push to data table1** node to point to the correct data table for storing results.\n\n### Customization\n\nYou can adjust the ranking/sorting logic inside the two code nodes (`Sort Reddit solo` and `Classement Reddit1`) to weight posts by upvotes, comments, recency, or other criteria. The Apify actor parameters in `Reddit solo get post` can be tuned to change the number of posts fetched per query or subreddit scope."
},
"typeVersion": 1
},
{
"id": "f3dafbfd-4379-4a3f-867b-689e1aeeea05",
"name": "Sticky Note24",
"type": "n8n-nodes-base.stickyNote",
"position": [
928,
992
],
"parameters": {
"color": 7,
"width": 400,
"height": 320,
"content": "## Trigger and fetch queries\n\nA schedule trigger fires the workflow and retrieves the list of Reddit search queries from a data table to process."
},
"typeVersion": 1
},
{
"id": "d7146361-d7dc-4183-9af6-71ac656a50c6",
"name": "Sticky Note25",
"type": "n8n-nodes-base.stickyNote",
"position": [
1408,
992
],
"parameters": {
"color": 7,
"width": 400,
"height": 320,
"content": "## Loop and scrape Reddit posts\n\nIterates over each query in a batch loop and calls the Apify Reddit scraper API to fetch raw posts for that query."
},
"typeVersion": 1
},
{
"id": "f78712d1-386a-4bf9-bc78-f62a00369154",
"name": "Sticky Note26",
"type": "n8n-nodes-base.stickyNote",
"position": [
1872,
992
],
"parameters": {
"color": 7,
"width": 416,
"height": 320,
"content": "## Sort and rank results\n\nTwo code nodes process the raw scraped data \u2014 first sorting posts into a simplified structure, then applying a full ranking algorithm."
},
"typeVersion": 1
},
{
"id": "f691043b-295a-4b3d-9866-4f295cf194c4",
"name": "Sticky Note27",
"type": "n8n-nodes-base.stickyNote",
"position": [
2336,
784
],
"parameters": {
"color": 7,
"height": 528,
"content": "## Send email and store results\n\nDispatches the ranked Reddit results via Gmail and pushes the data into a storage table for historical tracking."
},
"typeVersion": 1
},
{
"id": "fa2a7763-4c96-4dfe-90b4-3a6576fe7a97",
"name": "Fetch Reddit Posts via Apify1",
"type": "n8n-nodes-base.httpRequest",
"notes": "Post the request on apify",
"position": [
1664,
1152
],
"parameters": {
"url": "https://api.apify.com/v2/acts/trudax~reddit-scraper-lite/run-sync-get-dataset-items",
"method": "POST",
"options": {},
"jsonBody": "={\n \"searches\": [\"{{ $json.Query }}\"],\n \"searchPosts\": true,\n \"searchComments\": false,\n \"searchCommunities\": false,\n \"searchUsers\": false,\n \"sort\": \"top\",\n \"time\": \"month\",\n \"maxItems\": 50,\n \"maxPostCount\": 50,\n \"maxComments\": 1,\n \"scrollTimeout\": 40,\n \"proxy\": {\n \"useApifyProxy\": true,\n \"apifyProxyGroups\": [\"RESIDENTIAL\"]\n }\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"nodeCredentialType": "apifyApi"
},
"credentials": {
"apifyApi": {
"name": "<your credential>"
},
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"executeOnce": false,
"notesInFlow": true,
"retryOnFail": false,
"typeVersion": 4.2
},
{
"id": "801f152f-3f86-4fb4-bf50-9226fb4b07ce",
"name": "Rank Reddit Posts1",
"type": "n8n-nodes-base.code",
"notes": "Sorts all posts + give them points depending on their likes + comments",
"position": [
2144,
1152
],
"parameters": {
"jsCode": "// Code pour n\u0153ud Code n8n - Classement Reddit\n// R\u00e9cup\u00e9rer le keyword dynamiquement\nconst keyword = $('Loop Over Reddit Queries').first().json.Query;\n\n// R\u00e9cup\u00e9rer les donn\u00e9es du n\u0153ud pr\u00e9c\u00e9dent\nconst redditData = $('Sort Reddit Posts by Score').all();\n\nconsole.log(`\ud83d\udce5 R\u00e9cup\u00e9ration des donn\u00e9es:`);\nconsole.log(`- Reddit: ${redditData.length} posts`);\n\n// Fonction pour d\u00e9terminer le level bas\u00e9 sur le score\nfunction getLevel(score) {\n if (score >= 10000) return 'High';\n if (score >= 1000) return 'Medium';\n return 'Low';\n}\n\n// Fonction pour extraire le subreddit\nfunction getAuthor(item) {\n const redditMatch = item.url.match(/\\/r\\/([^\\/]+)/);\n return redditMatch ? `r/${redditMatch[1]}` : 'user_inconnu';\n}\n\n// Transformer les donn\u00e9es Reddit\nconst redditPosts = redditData.map(item => ({\n json: {\n source: 'Reddit',\n keyword: keyword,\n author: getAuthor(item.json),\n content: (item.json.title || 'Pas de titre').substring(0, 50) + '...',\n score: item.json.score,\n level: getLevel(item.json.score),\n url: item.json.url,\n originalRank: item.json.rank\n }\n}));\n\n// Trier par score d\u00e9croissant\nconst sortedPosts = redditPosts.sort((a, b) => b.json.score - a.json.score);\n\n// Ajouter le rang unifi\u00e9\nconst rankedPosts = sortedPosts.map((post, index) => ({\n json: {\n ...post.json,\n rank: index + 1,\n date: new Date().toISOString().split('T')[0]\n }\n}));\n\n// Prendre le top 15\nconst topPosts = rankedPosts.slice(0, 15);\n\n// Statistiques par niveau\nconst stats = {\n total: topPosts.length,\n byLevel: {\n High: topPosts.filter(p => p.json.level === 'High').length,\n Medium: topPosts.filter(p => p.json.level === 'Medium').length,\n Low: topPosts.filter(p => p.json.level === 'Low').length\n }\n};\n\n// Log pour debug\nconsole.log(`\ud83c\udfc6 TOP ${topPosts.length} POSTS REDDIT - Mot-cl\u00e9: \"${keyword}\"`);\nconsole.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);\n\ntopPosts.forEach((post) => {\n const p = post.json;\n console.log(`${p.rank}. ${p.author} - Score: ${p.score.toLocaleString()} (${p.level})`);\n console.log(` Contenu: \"${p.content}\"`);\n console.log(` URL: ${p.url}`);\n console.log(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);\n});\n\nconsole.log(`\\n\ud83d\udcca STATISTIQUES:`);\nconsole.log(`Total: ${stats.total} posts`);\nconsole.log(`Par niveau: High(${stats.byLevel.High}) | Medium(${stats.byLevel.Medium}) | Low(${stats.byLevel.Low})`);\n\n// Retourner le classement\nreturn topPosts;"
},
"notesInFlow": true,
"typeVersion": 2
}
],
"connections": {
"Rank Reddit Posts1": {
"main": [
[
{
"node": "Send Reddit Report Email",
"type": "main",
"index": 0
},
{
"node": "Push Results to Data Table",
"type": "main",
"index": 0
}
]
]
},
"Get Reddit Query Rows": {
"main": [
[
{
"node": "Loop Over Reddit Queries",
"type": "main",
"index": 0
}
]
]
},
"Reddit Schedule Trigger": {
"main": [
[
{
"node": "Get Reddit Query Rows",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Reddit Queries": {
"main": [
[],
[
{
"node": "Fetch Reddit Posts via Apify1",
"type": "main",
"index": 0
}
]
]
},
"Send Reddit Report Email": {
"main": [
[
{
"node": "Loop Over Reddit Queries",
"type": "main",
"index": 0
}
]
]
},
"Sort Reddit Posts by Score": {
"main": [
[
{
"node": "Rank Reddit Posts1",
"type": "main",
"index": 0
}
]
]
},
"Fetch Reddit Posts via Apify1": {
"main": [
[
{
"node": "Sort Reddit Posts by Score",
"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.
apifyApigmailOAuth2httpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
๐บ Full walkthrough video: https://www.youtube.com/watch?v=Me4d4BILvHk
Source: https://n8n.io/workflows/14298/ โ original creator credit. Request a take-down โ
More Web Scraping workflows โ ยท Browse all categories โ
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
> Watch the full Youtube Video Tutorial [](https://youtu.be/Y-wUr2-UYZk)
This workflow is for social media managers, content strategists, and marketing teams who need to track TikTok engagement trends across multiple hashtags on a recurring basis โ without manually checkin
This workflow automatically scrapes business leads from Google Maps on a daily schedule and ensures only high-quality, unique leads are processed. New businesses are cleaned, validated, and deduplicat
Perfect for social media managers, content creators, and personal brands who want to stay relevant on X without manually tracking trends or writing posts every day. The workflow runs 3 times daily by
Manually checking websites for updates or competitor changes can be tedious. This workflow automates the process by scraping target pages, capturing screenshots, and analyzing content changes using Fi