Reddit ASO Post Pull Flow

    Shared 1/27/2026

    8 views

    Visual Workflow

    JSON Code

    {
      "id": "XRLAqULlKcPaaUUu",
      "meta": {
        "instanceId": "dacbf730ada3d4913bb2d96044c5270da2c9e600d30d4118b5232966bff0b4d2",
        "templateCredsSetupCompleted": true
      },
      "name": "Reddit ASO Post Pull Flow",
      "tags": [],
      "nodes": [
        {
          "id": "0f4d9ed3-40d5-4eb9-a5cd-34aaa9a0949c",
          "name": "Schedule Trigger",
          "type": "n8n-nodes-base.scheduleTrigger",
          "position": [
            0,
            0
          ],
          "parameters": {
            "rule": {
              "interval": [
                {
                  "field": "weeks",
                  "triggerAtDay": [
                    1
                  ],
                  "triggerAtHour": 7
                }
              ]
            }
          },
          "typeVersion": 1.2
        },
        {
          "id": "ce3bfc13-e0f4-454c-8e7f-1ed1281706f0",
          "name": "Get many posts",
          "type": "n8n-nodes-base.reddit",
          "position": [
            416,
            0
          ],
          "parameters": {
            "filters": {
              "category": "hot"
            },
            "operation": "getAll",
            "subreddit": "AppStoreOptimization"
          },
          "credentials": {
            "redditOAuth2Api": {
              "id": "j2x0Gi7wjKzoNdFy",
              "name": "Reddit account"
            }
          },
          "typeVersion": 1
        },
        {
          "id": "852240cb-5640-4e7d-af87-0d9bb667e3e8",
          "name": "Compute Window",
          "type": "n8n-nodes-base.code",
          "position": [
            208,
            0
          ],
          "parameters": {
            "mode": "runOnceForEachItem",
            "jsCode": "// Europe/London weekly window: last 7 days at runtime\nconst now = new Date();\nconst sevenDaysAgo = new Date(now.getTime() - 7*24*60*60*1000);\n\n// Reddit search uses UNIX seconds in timestamp:START..END via CloudSearch syntax\nconst startUnix = Math.floor(sevenDaysAgo.getTime() / 1000);\nconst endUnix   = Math.floor(now.getTime() / 1000);\n\n// build \"dd-mm-yyyy\" in UK order\nconst dd = String(sevenDaysAgo.getDate()).padStart(2, '0');\nconst mm = String(sevenDaysAgo.getMonth() + 1).padStart(2, '0');\nconst yyyy = sevenDaysAgo.getFullYear();\n\nconst wcName = `w/c ${yyyy}-${mm}-${dd}`;\n\nreturn {\n  json: {\n    startUnix,\n    endUnix,\n    // Optional: a human label for the sheet\n    label: `r_apps_${new Date().toISOString().slice(0,10)}`,\n    wcName,   // <- \"w/c 23-10-2025\"\n  }\n};"
          },
          "typeVersion": 2
        },
        {
          "id": "05ae1a0a-d34f-4cb3-a713-8e1bd8378f13",
          "name": "Parse Posts",
          "type": "n8n-nodes-base.code",
          "position": [
            624,
            0
          ],
          "parameters": {
            "jsCode": "// Step 4: Parse Posts (works with both shapes: flat items OR data.children)\nlet posts = [];\n\n// Case A: HTTP node returned a single item with json.data.children[]\nif (items.length === 1 && items[0].json?.data?.children) {\n  posts = items[0].json.data.children.map(c => c.data ?? c);\n} else {\n  // Case B: Each incoming item is already a flat Reddit post object\n  posts = items.map(i => i.json);\n}\n\nconst iosRe = /https?:\\/\\/(?:itunes\\.apple\\.com|apps\\.apple\\.com)\\/[^\\s)]+/gi;\nconst androidRe = /https?:\\/\\/play\\.google\\.com\\/store\\/apps\\/details[^\\s)]+/gi;\n\n// Heuristics to tidy app name from the title\nfunction deriveAppName(title) {\n  if (!title) return '';\n  let t = title\n    .replace(/\\[[^\\]]+\\]/g, '')   // [iOS], [Release], etc.\n    .replace(/\\([^)]+\\)/g, '')    // (Beta), etc.\n    .replace(/\\s{2,}/g, ' ')\n    .trim();\n\n  const splitters = [' - ', ' | ', ' — ', ' – '];\n  for (const s of splitters) {\n    if (t.includes(s)) {\n      const first = t.split(s)[0].trim();\n      if (first.length >= 3) return first;\n    }\n  }\n  return t;\n}\n\nfunction truncate(s, n = 280) {\n  if (!s) return '';\n  const clean = String(s).replace(/\\s+/g, ' ').trim();\n  return clean.length > n ? clean.slice(0, n - 1) + '…' : clean;\n}\n\nconst out = posts.map(p => {\n  const title = p.title || '';\n  const selftext = p.selftext || '';\n\n  // Combine potential link sources\n  const combined = [\n    p.url_overridden_by_dest,\n    p.url,\n    selftext,\n  ].filter(Boolean).join('\\n');\n\n  const iosLinks = Array.from(combined.matchAll(iosRe)).map(m => m[0]);\n  const androidLinks = Array.from(combined.matchAll(androidRe)).map(m => m[0]);\n\n  const uniq = arr => Array.from(new Set(arr));\n\n  return {\n    json: {\n      reddit_id: p.id || (p.name && String(p.name).replace(/^t3_/, '')) || '',\n      created_utc: p.created_utc ?? null,\n      created_at: p.created_utc ? new Date(p.created_utc * 1000).toISOString() : '',\n      created_at_clean: p.created_utc\n  ? new Date(p.created_utc * 1000).toLocaleString('en-GB', {\n      timeZone: 'Europe/London',\n      day: '2-digit',\n      month: 'short',\n      year: 'numeric',\n      hour: '2-digit',\n      minute: '2-digit',\n    })\n  : '',\n      post_title: title,\n      app_name: deriveAppName(title),\n      summary: truncate(selftext || title, 280),\n      key_info: truncate(selftext, 600),\n      ios_links: uniq(iosLinks).join(' | '),\n      android_links: uniq(androidLinks).join(' | '),\n      post_url: p.permalink ? `https://www.reddit.com${p.permalink}` : (p.url || ''),\n      author: p.author || '',\n      upvotes: p.ups ?? p.score ?? 0,\n      subreddit: p.subreddit || p.subreddit_name_prefixed || '',\n    }\n  };\n});\n\n// Optional: if you only want rows with at least some useful info, you can filter here\n// return out.filter(r => r.json.app_name || r.json.ios_links || r.json.android_links);\n\nreturn out;\n"
          },
          "typeVersion": 2
        },
        {
          "id": "a308ce3c-2a57-4198-88d5-2e5dac22c020",
          "name": "No Operation, do nothing",
          "type": "n8n-nodes-base.noOp",
          "position": [
            1312,
            128
          ],
          "parameters": {},
          "typeVersion": 1
        },
        {
          "id": "11b96e44-277e-4d71-954d-224a4b7bff6c",
          "name": "Keep Useful Rows",
          "type": "n8n-nodes-base.if",
          "position": [
            832,
            0
          ],
          "parameters": {
            "options": {},
            "conditions": {
              "options": {
                "version": 2,
                "leftValue": "",
                "caseSensitive": true,
                "typeValidation": "strict"
              },
              "combinator": "or",
              "conditions": [
                {
                  "id": "73f943b4-76f7-46f3-90b0-b914d7c5e5f5",
                  "operator": {
                    "type": "boolean",
                    "operation": "true",
                    "singleValue": true
                  },
                  "leftValue": "={{ $json.app_name && $json.app_name.length > 2 }}",
                  "rightValue": ""
                },
                {
                  "id": "dac0beec-ea3f-4744-b3e5-0785e184cd06",
                  "operator": {
                    "type": "boolean",
                    "operation": "true",
                    "singleValue": true
                  },
                  "leftValue": "={{ $json.ios_links || $json.android_links }}",
                  "rightValue": ""
                }
              ]
            }
          },
          "typeVersion": 2.2
        },
        {
          "id": "adcdd308-3d6f-4053-857d-6837905427b7",
          "name": "Create spreadsheet",
          "type": "n8n-nodes-base.googleSheets",
          "position": [
            592,
            -192
          ],
          "parameters": {
            "title": "={{ 'Reddit ASO Pull - ' + $now.toISO().split('T')[0] }}",
            "options": {},
            "resource": "spreadsheet"
          },
          "credentials": {
            "googleSheetsOAuth2Api": {
              "id": "zxDX0aYCtj2zn2PV",
              "name": "Sheets GoogleAuth"
            }
          },
          "typeVersion": 4.7
        },
        {
          "id": "1ca88c41-741b-460d-a841-f312f64b8328",
          "name": "Sheet Meta1",
          "type": "n8n-nodes-base.set",
          "position": [
            384,
            -192
          ],
          "parameters": {
            "options": {},
            "assignments": {
              "assignments": [
                {
                  "id": "faebbcaa-78be-4633-9d17-1302103d3eca",
                  "name": "run",
                  "type": "string",
                  "value": "1"
                }
              ]
            }
          },
          "typeVersion": 3.4
        },
        {
          "id": "092676ad-f586-468d-92b0-630bb2bc1c63",
          "name": "Append Posts",
          "type": "n8n-nodes-base.googleSheets",
          "position": [
            1904,
            -16
          ],
          "parameters": {
            "columns": {
              "value": {
                "author": "={{ $json.author }}",
                "summary": "={{ $json.summary }}",
                "upvotes": "={{ $json.upvotes }}",
                "app_name": "={{ $json.app_name }}",
                "key_info": "={{ $json.key_info }}",
                "post_url": "={{ $json.post_url }}",
                "ios_links": "={{ $json.ios_links }}",
                "reddit_id": "={{ $json.reddit_id }}",
                "created_at": "={{ $json.created_at_clean }}",
                "post_title": "={{ $json.post_title }}",
                "android_links": "={{ $json.android_links }}"
              },
              "schema": [
                {
                  "id": "reddit_id",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "reddit_id",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "created_at",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "created_at",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "post_title",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "post_title",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "app_name",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "app_name",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "summary",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "summary",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "key_info",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "key_info",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "ios_links",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "ios_links",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "android_links",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "android_links",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "post_url",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "post_url",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "author",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "author",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "upvotes",
                  "type": "string",
                  "display": true,
                  "removed": false,
                  "required": false,
                  "displayName": "upvotes",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                }
              ],
              "mappingMode": "defineBelow",
              "matchingColumns": [],
              "attemptToConvertTypes": false,
              "convertFieldsToString": false
            },
            "options": {
              "cellFormat": "USER_ENTERED"
            },
            "operation": "append",
            "sheetName": {
              "__rl": true,
              "mode": "name",
              "value": "Sheet1"
            },
            "documentId": {
              "__rl": true,
              "mode": "id",
              "value": "={{ $node[\"Create spreadsheet\"].json.spreadsheetId }}"
            }
          },
          "credentials": {
            "googleSheetsOAuth2Api": {
              "id": "zxDX0aYCtj2zn2PV",
              "name": "Sheets GoogleAuth"
            }
          },
          "typeVersion": 4.7
        },
        {
          "id": "c273d7e9-0763-41b7-aa3b-7bbb1eda2412",
          "name": "Build Headers",
          "type": "n8n-nodes-base.code",
          "position": [
            800,
            -192
          ],
          "parameters": {
            "jsCode": "return [\n  {\n    json: {\n      reddit_id: \"reddit_id\",\n      created_at: \"created_at_clean\",\n      post_title: \"post_title\",\n      app_name: \"app_name\",\n      summary: \"summary\",\n      key_info: \"key_info\",\n      ios_links: \"ios_links\",\n      android_links: \"android_links\",\n      post_url: \"post_url\",\n      author: \"author\",\n      upvotes: \"upvotes\",\n    }\n  }\n];\n"
          },
          "typeVersion": 2
        },
        {
          "id": "1b43bc2e-fffa-4342-ab0d-ebfe55bccafa",
          "name": "Merge for Append",
          "type": "n8n-nodes-base.merge",
          "position": [
            1600,
            -48
          ],
          "parameters": {},
          "typeVersion": 3.2
        },
        {
          "id": "89dd1afb-5a00-4bdd-bf5e-ecc6a162b987",
          "name": "Append Rows to Sheet",
          "type": "n8n-nodes-base.googleSheets",
          "position": [
            992,
            -192
          ],
          "parameters": {
            "columns": {
              "value": {},
              "schema": [
                {
                  "id": "kind",
                  "type": "string",
                  "display": true,
                  "removed": true,
                  "required": false,
                  "displayName": "kind",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "id",
                  "type": "string",
                  "display": true,
                  "removed": true,
                  "required": false,
                  "displayName": "id",
                  "defaultMatch": true,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "name",
                  "type": "string",
                  "display": true,
                  "removed": true,
                  "required": false,
                  "displayName": "name",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                },
                {
                  "id": "mimeType",
                  "type": "string",
                  "display": true,
                  "removed": true,
                  "required": false,
                  "displayName": "mimeType",
                  "defaultMatch": false,
                  "canBeUsedToMatch": true
                }
              ],
              "mappingMode": "defineBelow",
              "matchingColumns": [
                "row_number"
              ],
              "attemptToConvertTypes": false,
              "convertFieldsToString": false
            },
            "options": {},
            "operation": "append",
            "sheetName": {
              "__rl": true,
              "mode": "name",
              "value": "Sheet1"
            },
            "documentId": {
              "__rl": true,
              "mode": "id",
              "value": "={{ $node[\"Create spreadsheet\"].json.spreadsheetId }}"
            }
          },
          "credentials": {
            "googleSheetsOAuth2Api": {
              "id": "zxDX0aYCtj2zn2PV",
              "name": "Sheets GoogleAuth"
            }
          },
          "typeVersion": 4.7
        },
        {
          "id": "44e26a96-0fcc-4c3d-828b-71c928a44de3",
          "name": "Send to Timi",
          "type": "n8n-nodes-base.slack",
          "position": [
            2400,
            -32
          ],
          "webhookId": "2d4f25c8-a88a-47bf-aaa8-b393d8c51569",
          "parameters": {
            "text": "=📊 Weekly Reddit ASO roundup is ready! 👉 <{{$item(0).$node[\"Create spreadsheet\"].json.spreadsheetUrl}}|Open the Google Sheet>\n\nRows added: {{$items().length}}\n\nGenerated automatically by Heave 🚀",
            "user": {
              "__rl": true,
              "mode": "list",
              "value": "U09E87LLE4T",
              "cachedResultName": "timi"
            },
            "select": "user",
            "otherOptions": {
              "unfurl_media": false
            },
            "authentication": "oAuth2"
          },
          "credentials": {
            "slackOAuth2Api": {
              "id": "4fQTc59XSdpTH9YM",
              "name": "Slack OAuth2"
            }
          },
          "typeVersion": 2.3
        },
        {
          "id": "526defe0-1bda-4c57-93df-5eddd6fff35e",
          "name": "One Send Meta",
          "type": "n8n-nodes-base.set",
          "position": [
            2144,
            -16
          ],
          "parameters": {
            "options": {},
            "assignments": {
              "assignments": [
                {
                  "id": "2ee241ef-d077-49ea-a110-d4f219314e6b",
                  "name": "run",
                  "type": "number",
                  "value": 1
                }
              ]
            }
          },
          "executeOnce": true,
          "typeVersion": 3.4
        },
        {
          "id": "ea1d45e1-a4e6-4a6b-aa8f-acf53e45a9c5",
          "name": "Move to Weekly Folder",
          "type": "n8n-nodes-base.googleDrive",
          "position": [
            1376,
            -192
          ],
          "parameters": {
            "fileId": {
              "__rl": true,
              "mode": "id",
              "value": "={{ $node[\"Create spreadsheet\"].json.spreadsheetId }}"
            },
            "driveId": {
              "__rl": true,
              "mode": "id",
              "value": "=My Drive"
            },
            "folderId": {
              "__rl": true,
              "mode": "id",
              "value": "={{ $node[\"Find Weekly Folder\"].json.id }}\n\n"
            },
            "operation": "move"
          },
          "credentials": {
            "googleDriveOAuth2Api": {
              "id": "SZWdCDshOOVpdHy7",
              "name": "GoogleAuth"
            }
          },
          "typeVersion": 3
        },
        {
          "id": "a53a9919-76b6-493f-afe4-c15e0c8f25e6",
          "name": "Find Weekly Folder",
          "type": "n8n-nodes-base.googleDrive",
          "position": [
            1200,
            -192
          ],
          "parameters": {
            "limit": 1,
            "filter": {},
            "options": {},
            "resource": "fileFolder",
            "queryString": "=name = '{{$node[\"Compute Window\"].json.wcName}}' and mimeType = 'application/vnd.google-apps.folder' and trashed = false",
            "searchMethod": "query"
          },
          "credentials": {
            "googleDriveOAuth2Api": {
              "id": "SZWdCDshOOVpdHy7",
              "name": "GoogleAuth"
            }
          },
          "typeVersion": 3
        }
      ],
      "active": true,
      "pinData": {},
      "settings": {
        "executionOrder": "v1"
      },
      "versionId": "59971edd-592e-4c40-ac08-7016bd7af240",
      "connections": {
        "Parse Posts": {
          "main": [
            [
              {
                "node": "Keep Useful Rows",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Sheet Meta1": {
          "main": [
            [
              {
                "node": "Create spreadsheet",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Append Posts": {
          "main": [
            [
              {
                "node": "One Send Meta",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Build Headers": {
          "main": [
            [
              {
                "node": "Append Rows to Sheet",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "One Send Meta": {
          "main": [
            [
              {
                "node": "Send to Timi",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Compute Window": {
          "main": [
            [
              {
                "node": "Get many posts",
                "type": "main",
                "index": 0
              },
              {
                "node": "Sheet Meta1",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Get many posts": {
          "main": [
            [
              {
                "node": "Parse Posts",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Keep Useful Rows": {
          "main": [
            [
              {
                "node": "Merge for Append",
                "type": "main",
                "index": 0
              }
            ],
            [
              {
                "node": "No Operation, do nothing",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Merge for Append": {
          "main": [
            [
              {
                "node": "Append Posts",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Schedule Trigger": {
          "main": [
            [
              {
                "node": "Compute Window",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Create spreadsheet": {
          "main": [
            [
              {
                "node": "Build Headers",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Find Weekly Folder": {
          "main": [
            [
              {
                "node": "Move to Weekly Folder",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Append Rows to Sheet": {
          "main": [
            [
              {
                "node": "Find Weekly Folder",
                "type": "main",
                "index": 0
              }
            ]
          ]
        },
        "Move to Weekly Folder": {
          "main": [
            [
              {
                "node": "Merge for Append",
                "type": "main",
                "index": 1
              }
            ]
          ]
        }
      }
    }