{
  "name": "Ad Copy That Passes Review — AuditSocials policy guardrail",
  "nodes": [
    {
      "parameters": {},
      "id": "trigger-1",
      "name": "Run",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -320,
        300
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "f-content",
              "name": "content",
              "type": "string",
              "value": "Lose 10kg in 7 days GUARANTEED! 💊 Our miracle keto gummies melt fat overnight — no diet, no exercise. Doctors HATE this. FDA-approved secret. Only 3 left, buy now!"
            },
            {
              "id": "f-platform",
              "name": "platform",
              "type": "string",
              "value": "Google"
            },
            {
              "id": "f-type",
              "name": "contentType",
              "type": "string",
              "value": "ad"
            }
          ]
        },
        "options": {}
      },
      "id": "draft-1",
      "name": "Draft Content",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -120,
        300
      ],
      "notes": "Replace this with your generator (LLM / RSS / form). Just output: content, platform, contentType."
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://www.auditsocials.com/api/v1/compliance-check",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_AUDITSOCIALS_API_KEY"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"content\": {{ JSON.stringify($json.content) }},\n  \"platforms\": [{{ JSON.stringify($json.platform) }}],\n  \"contentType\": {{ JSON.stringify($json.contentType) }}\n}",
        "options": {}
      },
      "id": "check-1",
      "name": "AuditSocials Policy Check",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        120,
        300
      ],
      "notes": "Get a free key at auditsocials.com/compliance-api  (50 checks/mo, no card)."
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Branch on REAL blockers (firm matches or critical/high severity),\n// not on the verdict — soft 'possibly_risky' notes should not block publishing.\nconst r = $json;\nconst findings = Array.isArray(r.findings) ? r.findings : [];\nconst isBlocker = (f) => f.confidence === 'firm' || f.severity === 'critical' || f.severity === 'high';\nconst blockers = findings.filter(isBlocker);\nconst advisories = findings.filter((f) => !isBlocker(f));\nconst d = $('Draft Content').item.json;\nconst fixPrompt = blockers.length\n  ? `Rewrite the following ${d.contentType} so it complies with ${d.platform} advertising policy. `\n    + `Keep the marketing intent and tone. Fix EVERY issue below. Return ONLY the rewritten text.\\n\\nIssues to fix:\\n`\n    + blockers.map((f) => `- \"${f.matchedText}\": ${f.issue} FIX: ${f.suggestion}`).join('\\n')\n    + `\\n\\nOriginal:\\n${d.content}`\n  : '';\nreturn { json: { verdict: r.verdict, findings, blockers, advisories, hasBlockers: blockers.length > 0, blockerCount: blockers.length, advisoryCount: advisories.length, fixPrompt, content: d.content, platform: d.platform, contentType: d.contentType, credits: r.credits } };"
      },
      "id": "eval-1",
      "name": "Evaluate Risk",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        340,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "typeValidation": "loose",
            "version": 2
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "c-1",
              "leftValue": "={{ $json.hasBlockers }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        },
        "options": {}
      },
      "id": "if-1",
      "name": "Real blockers?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        560,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_OPENAI_API_KEY"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"model\": \"gpt-4o-mini\",\n  \"temperature\": 0.4,\n  \"messages\": [{ \"role\": \"user\", \"content\": {{ JSON.stringify($json.fixPrompt) }} }]\n}",
        "options": {}
      },
      "id": "rewrite-1",
      "name": "AI Rewrite (fix blockers)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        780,
        180
      ],
      "notes": "Swap for Anthropic/any model — it just needs to return the rewritten text."
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Pull the rewritten text and carry the platform/type forward for the re-check.\nconst rewritten = ($json.choices && $json.choices[0] && $json.choices[0].message && $json.choices[0].message.content || '').trim();\nconst ev = $('Evaluate Risk').item.json;\nreturn { json: { content: rewritten, platform: ev.platform, contentType: ev.contentType } };"
      },
      "id": "extract-1",
      "name": "Take Rewrite",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        180
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://www.auditsocials.com/api/v1/compliance-check",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_AUDITSOCIALS_API_KEY"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"content\": {{ JSON.stringify($json.content) }},\n  \"platforms\": [{{ JSON.stringify($json.platform) }}],\n  \"contentType\": {{ JSON.stringify($json.contentType) }}\n}",
        "options": {}
      },
      "id": "recheck-1",
      "name": "Re-check",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1220,
        180
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Compose the final report after one auto-fix pass.\nconst recheck = $json;\nconst findings = Array.isArray(recheck.findings) ? recheck.findings : [];\nconst isBlocker = (f) => f.confidence === 'firm' || f.severity === 'critical' || f.severity === 'high';\nconst remaining = findings.filter(isBlocker);\nconst first = $('Evaluate Risk').item.json;\nconst cleanDraft = $('Take Rewrite').item.json.content;\nconst status = remaining.length === 0 ? 'READY_TO_PUBLISH' : 'NEEDS_HUMAN_REVIEW';\nreturn { json: {\n  status,\n  autoFixed: true,\n  blockersBefore: first.blockerCount,\n  blockersAfter: remaining.length,\n  cleanDraft,\n  remainingBlockers: remaining,\n  advisories: findings.filter((f) => !isBlocker(f)),\n  report: `Auto-fix applied. Blockers ${first.blockerCount} → ${remaining.length}. Status: ${status}.`\n} };"
      },
      "id": "report-fixed",
      "name": "Report (auto-fixed)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1440,
        180
      ]
    },
    {
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// No real blockers — publishable. Surface soft advisories for reference.\nconst e = $json;\nreturn { json: {\n  status: 'READY_TO_PUBLISH',\n  autoFixed: false,\n  blockersBefore: 0,\n  blockersAfter: 0,\n  cleanDraft: e.content,\n  remainingBlockers: [],\n  advisories: e.advisories,\n  report: `No policy blockers. ${e.advisoryCount} soft advisory note(s). Status: READY_TO_PUBLISH.`\n} };"
      },
      "id": "report-clean",
      "name": "Report (clean)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        780,
        420
      ]
    },
    {
      "parameters": {},
      "id": "sink-1",
      "name": "→ Send to approval (Slack / Sheet / Notion)",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1000,
        300
      ],
      "notes": "Connect your destination here: Slack message, Google Sheet row, Notion page, or a native publish node."
    }
  ],
  "connections": {
    "Run": {
      "main": [
        [
          {
            "node": "Draft Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Draft Content": {
      "main": [
        [
          {
            "node": "AuditSocials Policy Check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AuditSocials Policy Check": {
      "main": [
        [
          {
            "node": "Evaluate Risk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Evaluate Risk": {
      "main": [
        [
          {
            "node": "Real blockers?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Real blockers?": {
      "main": [
        [
          {
            "node": "AI Rewrite (fix blockers)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Report (clean)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Rewrite (fix blockers)": {
      "main": [
        [
          {
            "node": "Take Rewrite",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Take Rewrite": {
      "main": [
        [
          {
            "node": "Re-check",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Re-check": {
      "main": [
        [
          {
            "node": "Report (auto-fixed)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Report (auto-fixed)": {
      "main": [
        [
          {
            "node": "→ Send to approval (Slack / Sheet / Notion)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Report (clean)": {
      "main": [
        [
          {
            "node": "→ Send to approval (Slack / Sheet / Notion)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "meta": {
    "templateCredsSetupCompleted": false
  }
}