[
  {
    "name": "Glassdoor Gmail apply-list",
    "description": "Unread Glassdoor job-alert emails -> keep Backend / AI / ML titles (skip Node.js backend) -> HTML digest email.",
    "active": false,
    "isArchived": false,
    "nodes": [
      {
        "parameters": {
          "pollTimes": {
            "item": [
              {
                "mode": "everyMinute"
              }
            ]
          },
          "simple": false,
          "filters": {
            "sender": "noreply@glassdoor.com",
            "readStatus": "unread"
          },
          "options": {},
          "maxResults": 50
        },
        "type": "n8n-nodes-base.gmailTrigger",
        "typeVersion": 1.4,
        "position": [
          80,
          176
        ],
        "id": "4ccc35bf-bb09-40dc-99f0-cf48bc3c4b0f",
        "name": "Gmail Trigger"
      },
      {
        "parameters": {
          "assignments": {
            "assignments": [
              {
                "id": "5fe5c2a3-d060-4ac4-82de-5f00f04bc5d1",
                "name": "Email body",
                "value": "={{ $json.text }}",
                "type": "string"
              },
              {
                "id": "fb693094-b236-452d-bdf4-715b0123bef2",
                "name": "Thread Id",
                "value": "={{ $json.threadId }}",
                "type": "string"
              },
              {
                "id": "c0ffee00-d060-4ac4-82de-5f00f04bc5d1",
                "name": "Message Id",
                "value": "={{ $json.id }}",
                "type": "string"
              }
            ]
          },
          "options": {}
        },
        "type": "n8n-nodes-base.set",
        "typeVersion": 3.5,
        "position": [
          304,
          176
        ],
        "id": "ba49cd53-2957-4c3c-b558-3a5a57bc1d0c",
        "name": "Set content"
      },
      {
        "parameters": {
          "modelId": {
            "__rl": true,
            "value": "models/gemini-2.5-flash-lite",
            "mode": "list",
            "cachedResultName": "models/gemini-2.5-flash-lite"
          },
          "messages": {
            "values": [
              {
                "content": "=You are a data extraction assistant. Extract job vacancy listings from a Glassdoor job-alert email.\n\nReturn ONLY a valid JSON array, with no markdown, code fences, or explanations.\n\nEach item must have:\n- \"id\": sequential integer starting from 1\n- \"position_name\": the job title as written in the email\n- \"company\": company name if present, otherwise \"\"\n- \"location\": location if present, otherwise \"\"\n- \"link\": the full vacancy URL, copied exactly (do not shorten or invent URLs)\n- \"snippet\": a short nearby text from the email (title, company, location). Do not include unsubscribe or footer text.\n\nInclude only links to a specific job listing (URLs with jobListingId, or glassdoor job listing pages).\n\nIgnore:\n- unsubscribe, privacy, settings, manage alerts\n- \"see more jobs\" search pages\n- \"create job alert\" / related-role / rjtRedirect links\n- social media, logos, tracking pixels\n\nIf there are no vacancy links, return [].\n\nEmail body:\n\"\"\"\n{{ $json['Email body'] }}\n\"\"\""
              }
            ]
          },
          "jsonOutput": true,
          "builtInTools": {},
          "options": {}
        },
        "type": "@n8n/n8n-nodes-langchain.googleGemini",
        "typeVersion": 1.2,
        "position": [
          480,
          176
        ],
        "id": "ca5fb33d-0aae-4543-b31d-9524804b6e48",
        "name": "Extract jobs",
        "executeOnce": false
      },
      {
        "parameters": {
          "jsCode": "function parseJobs(content) {\n  if (content == null) return [];\n  if (Array.isArray(content)) return content;\n  if (typeof content === 'object') {\n    if (Array.isArray(content.parts) && content.parts[0]?.text) {\n      return parseJobs(content.parts[0].text);\n    }\n    if (Array.isArray(content.jobs)) return content.jobs;\n    if (typeof content.link === 'string') return [content];\n    return parseJobs(content.text || content.output || content.content);\n  }\n  if (typeof content === 'string') {\n    const cleaned = content.replace(/```json/gi, '').replace(/```/g, '').trim();\n    const start = cleaned.indexOf('[');\n    const end = cleaned.lastIndexOf(']');\n    if (start === -1 || end === -1) return [];\n    try {\n      return parseJobs(JSON.parse(cleaned.slice(start, end + 1)));\n    } catch {\n      return [];\n    }\n  }\n  return [];\n}\n\nfunction jobListingId(link) {\n  const match = String(link).match(/jobListingId=(\\d+)/i);\n  if (match) return match[1];\n  const path = String(link).match(/\\/job-listing\\/[^/?]*-([0-9]{8,})/i);\n  return path ? path[1] : String(link);\n}\n\nconst setItems = $('Set content').all();\nconst threadId = setItems[0]?.json['Thread Id'] || '';\n\nfunction excerptFor(title, snippet, email) {\n  if (snippet) return String(snippet).slice(0, 500);\n  const t = String(title || '').trim();\n  if (!t) return email.slice(0, 400);\n  const idx = email.toLowerCase().indexOf(t.toLowerCase());\n  if (idx === -1) return email.slice(0, 400);\n  return email.slice(Math.max(0, idx - 120), Math.min(email.length, idx + t.length + 280));\n}\n\nconst seen = new Set();\nconst jobs = [];\nfor (const item of $input.all()) {\n  const parsed = parseJobs(item.json.content);\n  const email = setItems.map((s) => String(s.json['Email body'] || '')).join('\\n');\n  for (const job of parsed) {\n    if (!job || typeof job.link !== 'string' || !job.link.startsWith('http')) continue;\n    const key = jobListingId(job.link);\n    if (seen.has(key)) continue;\n    seen.add(key);\n    jobs.push({\n      id: job.id ?? jobs.length + 1,\n      position_name: job.position_name || '',\n      company: job.company || '',\n      location: job.location || '',\n      link: job.link,\n      snippet: excerptFor(job.position_name, job.snippet, email),\n      thread_id: threadId,\n      jobListingId: key,\n    });\n  }\n}\n\nif (!jobs.length) {\n  return [{ json: { gateSkip: true, position_name: '', company: '', location: '', link: '', snippet: '', thread_id: threadId, jobListingId: '' } }];\n}\n\nreturn jobs.map((job) => ({ json: job }));\n",
          "mode": "runOnceForAllItems"
        },
        "type": "n8n-nodes-base.code",
        "typeVersion": 2,
        "position": [
          704,
          176
        ],
        "id": "c1a6d0f2-7c41-4f8a-9d2e-3b8c1f0a9e11",
        "name": "Parse vacancy JSON"
      },
      {
        "parameters": {
          "jsCode": "const BACKEND = /back[\\s-]?end/i;\nconst AI = /\\bai\\b|artificial intelligence|ai[\\/\\s-]?ml/i;\nconst ML = /\\bml\\b|machine learning|ai[\\/\\s-]?ml/i;\nconst NODE = /node[\\s.]?js|\\bnodejs\\b/i;\n\nfunction titleOf(job) {\n  return String(job.position_name || '');\n}\n\nfunction passesGate(job) {\n  const title = titleOf(job);\n  const hasBackend = BACKEND.test(title);\n  const hasAi = AI.test(title);\n  const hasMl = ML.test(title);\n  if (!hasBackend && !hasAi && !hasMl) return false;\n  if (hasBackend && NODE.test(title)) return false;\n  return true;\n}\n\nconst items = $input.all();\nif (items.length === 1 && items[0].json.gateSkip) return items;\n\nconst kept = items.filter((item) => !item.json.gateSkip && passesGate(item.json));\nif (kept.length) return kept.map((item) => ({ json: item.json }));\n\nreturn [{\n  json: {\n    gateSkip: true,\n    position_name: '',\n    company: '',\n    location: '',\n    link: '',\n    snippet: '',\n    thread_id: items[0]?.json.thread_id || '',\n    jobListingId: '',\n  },\n}];\n",
          "mode": "runOnceForAllItems"
        },
        "type": "n8n-nodes-base.code",
        "typeVersion": 2,
        "position": [
          928,
          176
        ],
        "id": "a1b2c3d4-e5f6-4789-a012-3456789abcde",
        "name": "Title gate"
      },
      {
        "parameters": {
          "modelId": {
            "__rl": true,
            "value": "models/gemini-2.5-flash-lite",
            "mode": "list",
            "cachedResultName": "models/gemini-2.5-flash-lite"
          },
          "messages": {
            "values": [
              {
                "content": "=Classify whether this ONE job is worth applying to. Use the title first. Do not invent a stack.\n\nCandidate profile:\n- Track backend: title or role is backend / back-end (any language except Node.js as the primary stack).\n- Track ai_engineer: AI, ML, LLM, GenAI, or machine learning engineer.\n- Reject if the title is backend AND Node.js / nodejs (Node is the primary stack).\n- Reject non-dev roles (pilot, music, GTM, process/maintenance, office, customer service, etc.).\n- A generic \"Backend Engineer\" with no Node.js in the title is apply / backend.\n- Software Engineer with no backend, AI, or ML signal is reject.\n\nJob title: {{ $json.position_name }}\nCompany: {{ $json.company }}\nLocation: {{ $json.location }}\nSnippet:\n\"\"\"\n{{ $json.snippet }}\n\"\"\"\nLink: {{ $json.link }}\n\nReturn ONLY valid JSON:\n{\n  \"track\": \"backend\" | \"ai_engineer\" | \"reject\",\n  \"apply\": true or false,\n  \"reason\": \"one sentence\"\n}\n\napply is true only when track is backend or ai_engineer.\n"
              }
            ]
          },
          "jsonOutput": true,
          "builtInTools": {},
          "options": {}
        },
        "type": "@n8n/n8n-nodes-langchain.googleGemini",
        "typeVersion": 1.2,
        "position": [
          1264,
          80
        ],
        "id": "b2c3d4e5-f6a7-4890-b123-456789abcdef",
        "name": "Classify stack",
        "executeOnce": false
      },
      {
        "parameters": {
          "jsCode": "function extractJson(value) {\n  if (value == null) return {};\n  if (typeof value === 'object') {\n    if (typeof value.track !== 'undefined' || typeof value.apply !== 'undefined') return value;\n    if (Array.isArray(value.parts) && value.parts[0]?.text) return extractJson(value.parts[0].text);\n    return extractJson(value.output ?? value.text ?? value.content ?? value.message);\n  }\n  const str = String(value);\n  const fence = str.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n  const raw = (fence ? fence[1] : str).trim();\n  const start = raw.indexOf('{');\n  const end = raw.lastIndexOf('}');\n  if (start === -1 || end === -1) return { track: 'reject', apply: false, reason: raw.slice(0, 200) };\n  try {\n    return JSON.parse(raw.slice(start, end + 1));\n  } catch {\n    return { track: 'reject', apply: false, reason: 'Could not parse classifier output' };\n  }\n}\n\nconst titleGateItems = $('Title gate').all();\nconst job = (titleGateItems[$itemIndex] || $('Title gate').item).json;\nconst parsed = extractJson($json.content ?? $json);\nconst allowed = new Set(['backend', 'ai_engineer', 'php_laravel']);\nconst track = allowed.has(parsed.track) ? (parsed.track === 'php_laravel' ? 'backend' : parsed.track) : 'reject';\nconst apply = parsed.apply === true && track !== 'reject';\n\nreturn {\n  json: {\n    ...job,\n    track,\n    apply,\n    reason: parsed.reason || '',\n  },\n};\n",
          "mode": "runOnceForEachItem"
        },
        "type": "n8n-nodes-base.code",
        "typeVersion": 2,
        "position": [
          1488,
          80
        ],
        "id": "c3d4e5f6-a7b8-4901-c234-56789abcdef0",
        "name": "Parse classification"
      },
      {
        "parameters": {
          "jsCode": "const staticData = $getWorkflowStaticData('global');\nif (!Array.isArray(staticData.sentJobIds)) staticData.sentJobIds = [];\nconst sent = new Set(staticData.sentJobIds.map(String));\nconst fresh = [];\n\nfor (const item of $input.all()) {\n  if (item.json.apply !== true) continue;\n  const id = String(item.json.jobListingId || item.json.link || '');\n  if (!id || sent.has(id)) continue;\n  sent.add(id);\n  fresh.push(item.json);\n}\n\nstaticData.sentJobIds = Array.from(sent).slice(-2000);\nreturn [{ json: { jobs: fresh } }];\n",
          "mode": "runOnceForAllItems"
        },
        "type": "n8n-nodes-base.code",
        "typeVersion": 2,
        "position": [
          1824,
          80
        ],
        "id": "f6a7b8c9-d0e1-4234-f567-89abcdef0123",
        "name": "Dedupe sent ids"
      },
      {
        "parameters": {
          "jsCode": "function esc(value) {\n  return String(value ?? '')\n    .replace(/&/g, '&amp;')\n    .replace(/</g, '&lt;')\n    .replace(/>/g, '&gt;')\n    .replace(/\"/g, '&quot;');\n}\n\nfunction trackMeta(track) {\n  if (track === 'ai_engineer') {\n    return { label: 'AI / ML', bg: '#ceead6', fg: '#137333' };\n  }\n  return { label: 'Backend', bg: '#e8f0fe', fg: '#1967d2' };\n}\n\nfunction wrapEmail(inner, title, subtitle) {\n  const font = \"Roboto,Arial,Helvetica,sans-serif\";\n  return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <title>${esc(title)}</title>\n</head>\n<body style=\"margin:0;padding:0;background:#f8f9fa;font-family:${font};\">\n  <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"background:#f8f9fa;padding:24px 8px;\">\n    <tr>\n      <td align=\"center\">\n        <table role=\"presentation\" width=\"600\" cellpadding=\"0\" cellspacing=\"0\" style=\"max-width:600px;width:100%;background:#ffffff;border:1px solid #dadce0;border-radius:8px;overflow:hidden;\">\n          <tr>\n            <td>\n              <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">\n                <tr>\n                  <td style=\"height:4px;width:25%;background:#4285f4;font-size:0;line-height:0;\">&nbsp;</td>\n                  <td style=\"height:4px;width:25%;background:#ea4335;font-size:0;line-height:0;\">&nbsp;</td>\n                  <td style=\"height:4px;width:25%;background:#fbbc04;font-size:0;line-height:0;\">&nbsp;</td>\n                  <td style=\"height:4px;width:25%;background:#34a853;font-size:0;line-height:0;\">&nbsp;</td>\n                </tr>\n              </table>\n            </td>\n          </tr>\n          <tr>\n            <td style=\"padding:20px 28px 16px;border-bottom:1px solid #e8eaed;\">\n              <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">\n                <tr>\n                  <td valign=\"middle\" style=\"width:28px;\">\n                    <table role=\"presentation\" cellpadding=\"0\" cellspacing=\"2\">\n                      <tr>\n                        <td style=\"width:8px;height:8px;background:#4285f4;border-radius:50%;font-size:0;line-height:0;\">&nbsp;</td>\n                        <td style=\"width:8px;height:8px;background:#ea4335;border-radius:50%;font-size:0;line-height:0;\">&nbsp;</td>\n                      </tr>\n                      <tr>\n                        <td style=\"width:8px;height:8px;background:#fbbc04;border-radius:50%;font-size:0;line-height:0;\">&nbsp;</td>\n                        <td style=\"width:8px;height:8px;background:#34a853;border-radius:50%;font-size:0;line-height:0;\">&nbsp;</td>\n                      </tr>\n                    </table>\n                  </td>\n                  <td valign=\"middle\" style=\"padding-left:10px;font-size:14px;color:#5f6368;\">Apply list</td>\n                </tr>\n              </table>\n              <h1 style=\"margin:16px 0 4px;font-size:22px;line-height:28px;font-weight:400;color:#202124;\">${esc(title)}</h1>\n              <p style=\"margin:0;font-size:14px;line-height:20px;color:#5f6368;\">${esc(subtitle)}</p>\n            </td>\n          </tr>\n          <tr>\n            <td style=\"padding:20px 28px 8px;\">\n              ${inner}\n            </td>\n          </tr>\n          <tr>\n            <td style=\"padding:8px 28px 24px;font-size:12px;line-height:18px;color:#80868b;\">\n              Node.js backend titles are skipped. Only new Backend / AI / ML roles are listed.\n            </td>\n          </tr>\n        </table>\n      </td>\n    </tr>\n  </table>\n</body>\n</html>`;\n}\n\nconst jobs = Array.isArray($json.jobs) ? $json.jobs : [];\nconst date = $now.toFormat('yyyy-MM-dd');\nconst font = \"Roboto,Arial,Helvetica,sans-serif\";\n\nlet reviewed = [];\ntry {\n  reviewed = $('Parse vacancy JSON').all()\n    .map((item) => item.json)\n    .filter((job) => job && job.position_name && !job.gateSkip);\n} catch {\n  reviewed = [];\n}\n\nif (!jobs.length) {\n  const rows = reviewed.length\n    ? reviewed.map((job) => `\n      <tr>\n        <td style=\"padding:12px 0;border-bottom:1px solid #e8eaed;font-family:${font};font-size:14px;color:#202124;\">\n          <div style=\"font-size:16px;line-height:24px;color:#1a73e8;\">${esc(job.position_name)}</div>\n          <div style=\"font-size:13px;line-height:20px;color:#5f6368;\">${esc(job.company || 'Unknown')} \u00b7 ${esc(job.location || 'Unknown')}</div>\n        </td>\n      </tr>`).join('')\n    : `<tr><td style=\"padding:8px 0;font-family:${font};font-size:14px;color:#5f6368;\">No vacancy titles extracted.</td></tr>`;\n\n  const inner = `\n    <p style=\"margin:0 0 16px;font-family:${font};font-size:14px;line-height:22px;color:#202124;\">\n      No Backend / AI / ML roles in the latest Glassdoor alerts.\n    </p>\n    <p style=\"margin:0 0 8px;font-family:${font};font-size:12px;line-height:16px;color:#5f6368;\">\n      Reviewed ${reviewed.length} listing${reviewed.length === 1 ? '' : 's'}\n    </p>\n    <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">${rows}</table>\n  `;\n\n  return [{\n    json: {\n      count: 0,\n      subject: `Apply list \u2014 0 jobs \u2014 ${date}`,\n      body: wrapEmail(inner, 'No matching jobs', date),\n    },\n  }];\n}\n\nconst cards = jobs.map((job) => {\n  const meta = trackMeta(job.track);\n  const company = esc(job.company || 'Unknown');\n  const location = esc(job.location || 'Unknown');\n  const reason = job.reason\n    ? `<p style=\"margin:8px 0 0;font-family:${font};font-size:14px;line-height:20px;color:#5f6368;\">${esc(job.reason)}</p>`\n    : '';\n  return `\n    <table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" style=\"margin:0 0 12px;background:#ffffff;border:1px solid #dadce0;border-radius:8px;\">\n      <tr>\n        <td style=\"padding:16px 18px 18px;font-family:${font};\">\n          <span style=\"display:inline-block;margin:0 0 8px;padding:2px 8px;border-radius:4px;background:${meta.bg};color:${meta.fg};font-size:11px;line-height:16px;font-weight:500;\">${meta.label}</span>\n          <h2 style=\"margin:0 0 4px;font-size:18px;line-height:24px;font-weight:400;color:#1a73e8;\">${esc(job.position_name)}</h2>\n          <p style=\"margin:0;font-size:14px;line-height:20px;color:#5f6368;\">${company} \u00b7 ${location}</p>\n          ${reason}\n          <p style=\"margin:14px 0 0;\">\n            <a href=\"${esc(job.link)}\" style=\"display:inline-block;padding:8px 16px;background:#1a73e8;color:#ffffff;text-decoration:none;border-radius:4px;font-size:14px;line-height:20px;font-weight:500;\">Open listing</a>\n          </p>\n        </td>\n      </tr>\n    </table>`;\n}).join('');\n\nconst inner = `\n  <p style=\"margin:0 0 16px;font-family:${font};font-size:14px;line-height:22px;color:#202124;\">\n    ${jobs.length} role${jobs.length === 1 ? '' : 's'} worth a look.\n  </p>\n  ${cards}\n`;\n\nreturn [{\n  json: {\n    subject: `Apply list \u2014 ${jobs.length} job${jobs.length === 1 ? '' : 's'} \u2014 ${date}`,\n    body: wrapEmail(inner, 'Roles to apply to', `${date} \u00b7 ${jobs.length} match${jobs.length === 1 ? '' : 'es'}`),\n    count: jobs.length,\n  },\n}];\n",
          "mode": "runOnceForAllItems"
        },
        "type": "n8n-nodes-base.code",
        "typeVersion": 2,
        "position": [
          2048,
          176
        ],
        "id": "a7b8c9d0-e1f2-4345-a678-9abcdef01234",
        "name": "Build digest"
      },
      {
        "parameters": {
          "sendTo": "you@example.com",
          "subject": "={{ $json.subject }}",
          "emailType": "html",
          "message": "={{ $json.body }}",
          "options": {
            "appendAttribution": false
          },
          "resource": "message",
          "operation": "send"
        },
        "type": "n8n-nodes-base.gmail",
        "typeVersion": 2.2,
        "position": [
          2272,
          80
        ],
        "id": "b8c9d0e1-f2a3-4456-b789-abcdef012345",
        "name": "Send apply list"
      },
      {
        "parameters": {
          "conditions": {
            "options": {
              "caseSensitive": true,
              "leftValue": "",
              "typeValidation": "loose",
              "version": 2
            },
            "conditions": [
              {
                "id": "aa11bb22-cc33-4dd4-8ee5-ff6677889900",
                "leftValue": "={{ $json.gateSkip === true }}",
                "rightValue": false,
                "operator": {
                  "type": "boolean",
                  "operation": "false",
                  "singleValue": true
                }
              }
            ],
            "combinator": "and"
          }
        },
        "type": "n8n-nodes-base.if",
        "typeVersion": 2.2,
        "position": [
          1040,
          176
        ],
        "id": "11a22b33-c44d-455e-866f-9778899aabb0",
        "name": "Has stack candidates"
      },
      {
        "parameters": {
          "jsCode": "return [{ json: { jobs: [] } }];",
          "mode": "runOnceForAllItems"
        },
        "type": "n8n-nodes-base.code",
        "typeVersion": 2,
        "position": [
          1824,
          368
        ],
        "id": "22b33c44-d55e-466f-9778-8899aabbcc01",
        "name": "Empty apply list"
      },
      {
        "parameters": {
          "jsCode": "const ids = new Set();\nfor (const item of $('Gmail Trigger').all()) {\n  const id = item.json.id;\n  if (id) ids.add(String(id));\n}\nreturn Array.from(ids).map((messageId) => ({ json: { messageId } }));\n",
          "mode": "runOnceForAllItems"
        },
        "type": "n8n-nodes-base.code",
        "typeVersion": 2,
        "position": [
          2272,
          368
        ],
        "id": "55e66f77-a889-499a-aaab-bbccddeeff04",
        "name": "Trigger message ids"
      },
      {
        "parameters": {
          "resource": "message",
          "operation": "markAsRead",
          "messageId": "={{ $json.messageId || $json.id }}"
        },
        "type": "n8n-nodes-base.gmail",
        "typeVersion": 2.2,
        "position": [
          2496,
          368
        ],
        "id": "778899aa-c00b-4bbc-cccd-ddeeff001106",
        "name": "Mark Glassdoor read"
      }
    ],
    "connections": {
      "Gmail Trigger": {
        "main": [
          [
            {
              "node": "Set content",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Set content": {
        "main": [
          [
            {
              "node": "Extract jobs",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Extract jobs": {
        "main": [
          [
            {
              "node": "Parse vacancy JSON",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Parse vacancy JSON": {
        "main": [
          [
            {
              "node": "Title gate",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Title gate": {
        "main": [
          [
            {
              "node": "Has stack candidates",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Classify stack": {
        "main": [
          [
            {
              "node": "Parse classification",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Parse classification": {
        "main": [
          [
            {
              "node": "Dedupe sent ids",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Dedupe sent ids": {
        "main": [
          [
            {
              "node": "Build digest",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Build digest": {
        "main": [
          [
            {
              "node": "Send apply list",
              "type": "main",
              "index": 0
            },
            {
              "node": "Trigger message ids",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Has stack candidates": {
        "main": [
          [
            {
              "node": "Classify stack",
              "type": "main",
              "index": 0
            }
          ],
          [
            {
              "node": "Empty apply list",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Empty apply list": {
        "main": [
          [
            {
              "node": "Build digest",
              "type": "main",
              "index": 0
            }
          ]
        ]
      },
      "Trigger message ids": {
        "main": [
          [
            {
              "node": "Mark Glassdoor read",
              "type": "main",
              "index": 0
            }
          ]
        ]
      }
    },
    "settings": {
      "executionOrder": "v1",
      "binaryMode": "separate"
    },
    "staticData": null,
    "meta": {
      "templateCredsSetupCompleted": true
    },
    "pinData": {}
  }
]
