AutomationFlowsMarketing & Ads › Vk Public Discussion / Lead Source Connector (stage 3.5)

Vk Public Discussion / Lead Source Connector (stage 3.5)

13 - VK Public Discussion / Lead Source Connector (Stage 3.5). Uses googleSheets, httpRequest. Event-driven trigger; 24 nodes.

Event trigger★★★★☆ complexity24 nodesGoogle SheetsHTTP Request
Marketing & Ads Trigger: Event Nodes: 24 Complexity: ★★★★☆ Added:

This workflow follows the Google Sheets → 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 →

Download .json
{
  "name": "13 - VK Public Discussion / Lead Source Connector (Stage 3.5)",
  "nodes": [
    {
      "parameters": {
        "content": "## WF13 \u2014 VK Public Discussion / Lead Source Connector \u00b7 v0.3 (Stage 3.5, DEC-121/125/138)\n\n**\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:** \u041f\u0415\u0420\u0412\u042b\u0419 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a Lead Scout \u2014 \u041f\u0423\u0411\u041b\u0418\u0427\u041d\u042b\u0415 \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u044f VK (\u043f\u043e\u0441\u0442\u044b \u0438 \u041a\u041e\u041c\u041c\u0415\u041d\u0422\u0410\u0420\u0418\u0418 \u0433\u0440\u0443\u043f\u043f \u0438\u0437 allowlist). \u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0446\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u2014 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0421\u041f\u0420\u041e\u0421/\u0431\u043e\u043b\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0435\u0439 (\u043d\u0443\u0436\u0435\u043d \u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u0430, \u043f\u043b\u043e\u0445\u0430\u044f \u041a\u0418, \u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433 \u041f\u0422\u0421, \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430) \u2192 question_objection/public_comment \u2192 raw_market_records \u2192 WF14 Lead Scout. \u041f\u043b\u044e\u0441 \u0430\u0433\u0440\u0435\u0433\u0430\u0442\u044b \u0430\u0432\u0442\u043e\u0440\u043e\u0432 \u0434\u043b\u044f WF10.\n\n**\u0416\u0451\u0441\u0442\u043a\u0438\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430:** fixture-first ($0, \u0411\u0415\u0417 HTTP-\u0432\u044b\u0437\u043e\u0432\u043e\u0432); live_mode=false (guard \u0431\u0440\u043e\u0441\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443); \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0433\u0440\u0443\u043f\u043f\u044b/\u043f\u043e\u0441\u0442\u044b/\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u2014 \u041d\u0418\u041a\u0410\u041a\u0418\u0425 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0445 \u0447\u0430\u0442\u043e\u0432/\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0438 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432, \u0441\u043a\u0440\u044b\u0442\u044b\u0445 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043e\u0432, \u0430\u0432\u0442\u043e-\u0430\u0443\u0442\u0440\u0438\u0447\u0430 (CONTACT_AND_OUTREACH_POLICY). \u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u0422\u041e\u041b\u042c\u041a\u041e \u0435\u0441\u043b\u0438 \u0434\u043e\u0441\u043b\u043e\u0432\u043d\u043e \u0432\u0438\u0434\u0435\u043d \u0432 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u0435; profile_url \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439. \u0411\u0435\u0437 Claude. \u041a\u0430\u043d\u043e\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0445\u044d\u043d\u0434\u043e\u0444\u0444: raw_market_records \u2192 WF14 (Lead Scout) \u2192 public_lead_signals (\u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0431\u0435\u0437 \u0430\u0432\u0442\u043e-handoff); WF08 \u2014 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0443\u0442\u044c Stage 3, \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0445\u044d\u043d\u0434\u043e\u0444\u0444. \u041f\u0438\u0448\u0435\u0442: agent_requests / raw_market_records (40) / market_record_registry (15) / live_source_runs (23). MSK +03:00.\n\n**v0.3 LIVE (gated, INERT):** \u0434\u0432\u0430 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e VK API \u2014 wall.get (\u0441\u0442\u0435\u043d\u044b \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0433\u0440\u0443\u043f\u043f) \u0438 wall.getComments (\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u043f\u043e\u0434 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043f\u043e\u0441\u0442\u0430\u043c\u0438 \u2014 \u0433\u0434\u0435 \u0436\u0438\u0432\u0451\u0442 \u0441\u043f\u0440\u043e\u0441). \u0413\u0435\u0439\u0442: token=I_APPROVE_LIVE_VK_PUBLIC_DISCUSSION + live_group_allowlist \u0438/\u0438\u043b\u0438 live_post_allowlist \u2192 \u041e\u0422\u041a\u041b\u042e\u0427\u0401\u041d\u041d\u042b\u0419 HTTP (\u0442\u043e\u043a\u0435\u043d \u0422\u041e\u041b\u042c\u041a\u041e \u043a\u0430\u043a n8n-\u043a\u0440\u0435\u0434\u0435\u043d\u0448\u043b) \u2192 \u0438\u043d\u0435\u0440\u0442\u043d\u044b\u0439 \u043f\u0430\u0440\u0441\u0435\u0440 (\u0431\u0440\u043e\u0441\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443 \u0431\u0435\u0437 \u043e\u0442\u0432\u0435\u0442\u0430 API; \u043f\u0430\u0440\u0441\u0438\u0442 \u043e\u0431\u0435 \u0444\u043e\u0440\u043c\u044b). Runtime-\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 live = PENDING_STAGE_C_ACCEPTANCE. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u0441\u0451 \u0438\u043d\u0435\u0440\u0442\u043d\u043e.",
        "height": 760,
        "width": 620
      },
      "id": "wf13-note-1",
      "name": "Overview Note RU",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -460,
        -340
      ]
    },
    {
      "parameters": {
        "content": "## Setup & Test (fixture \u2014 Stage 3.5)\n\n1. \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c SPREADSHEET_ID \u0432 Google Sheets \u043d\u043e\u0434\u044b (Read registry + Append raw/registry/agent_requests/live_source_runs).\n2. \u0417\u0430\u043f\u0443\u0441\u043a \u0432\u0440\u0443\u0447\u043d\u0443\u044e (active=false). \u041d\u0415 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u0439 \u043d\u043e\u0434\u0435 \u2014 \u043f\u043e\u043b\u043d\u0430\u044f \u043f\u0440\u0438\u0451\u043c\u043a\u0430 = \u043f\u0430\u043a\u0435\u0442 Stage C.\n3. Fixture-\u043f\u0440\u043e\u0433\u043e\u043d (\u0441\u0438\u043d\u0442\u0435\u0442\u0438\u043a\u0430, $0): items_received=9, hard_skipped=1 (\u044e\u0440.\u0430\u0434\u0440\u0435\u0441), business_relevant=8, unique=7, duplicates=1 (in-batch \u0434\u0443\u0431\u043b\u044c comment 2011); raw +8 (audit), registry +7. \u0421\u0440\u0435\u0434\u0438 unique: 5 consumer-demand \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432 (question_objection/public_comment) \u2014 \u044d\u0442\u043e \u0432\u0445\u043e\u0434 Lead Scout; 1 competitor post; 1 market-news post. \u0422\u0435\u043b\u0435\u0444\u043e\u043d\u044b fixture = +7 000 ... (\u0441\u0438\u043d\u0442\u0435\u0442\u0438\u043a\u0430, \u043d\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435).\n4. \u041f\u043e\u0432\u0442\u043e\u0440: unique=0, duplicates=8, registry +0.\n5. Guard-\u0442\u0435\u0441\u0442: live_mode=true (fixture_mode=false) \u0431\u0435\u0437 \u0442\u043e\u043a\u0435\u043d\u0430 \u2192 \u043e\u0448\u0438\u0431\u043a\u0430 \u043d\u0430 LIVE VK Approval Gate. \u0412\u0435\u0440\u043d\u0443\u0442\u044c fixture_mode=true.\n6. End-to-end Lead Scout (Stage C): WF13 fixture \u2192 WF14 Execute once \u2192 public_lead_signals ~5 \u0441\u0442\u0440\u043e\u043a \u0441\u043e scored lead_score/score_band; \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0435\u043b\u0435\u0444\u043e\u043d/username \u2192 public_phone/public_username (manual_review); \u0440\u0435\u043a\u043b\u0430\u043c\u0430/\u043d\u043e\u0432\u043e\u0441\u0442\u0438 \u041d\u0415 \u0441\u0442\u0430\u043d\u043e\u0432\u044f\u0442\u0441\u044f \u043b\u0438\u0434\u0430\u043c\u0438; outreach_allowed=false.",
        "height": 640,
        "width": 620
      },
      "id": "wf13-note-2",
      "name": "Setup and Test Note RU",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        220,
        -340
      ]
    },
    {
      "parameters": {},
      "id": "wf13-start",
      "name": "Manual Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -420,
        560
      ]
    },
    {
      "parameters": {
        "jsCode": "// WF13 Public Discussion Connector \u2014 VK PUBLIC groups/posts/comments (DEC-121/125; Stage 3.5 lead-source, DEC-138).\n// Source decision (Avito -> Telegram -> VK): VK public discussions are the richest PUBLIC CONSUMER DEMAND source\n// (questions/objections/buying intent) and the first practical Lead Scout source. Fixture-first, $0, NO external\n// calls, no Claude, no auto-handoff. PUBLIC groups/posts/comments ONLY: no private chats/messages, no member\n// extraction, no hidden contacts, no auto-outreach (CONTACT_AND_OUTREACH_POLICY).\nfunction moscowIsoNow(){var m=new Date(Date.now()+10800000);return m.toISOString().replace('Z','+03:00');}\nfunction moscowStamp(){var z=function(n){return String(n).padStart(2,'0');};var m=new Date(Date.now()+10800000);return m.getUTCFullYear()+z(m.getUTCMonth()+1)+z(m.getUTCDate())+'_'+z(m.getUTCHours())+z(m.getUTCMinutes())+z(m.getUTCSeconds());}\nconst now=moscowIsoNow();\nconst stamp=moscowStamp();\nreturn [{ json: {\n  fixture_mode:true,\n  live_mode:false,\n  // --- live v0.3 GUARDED PATH (DEC-125/138): VK official API. INERT by default \u2014 live_mode=false, token empty,\n  // allowlists empty, HTTP node DISABLED. Two intended public methods:\n  //   wall.get        \u2014 public group walls (group/screen-name allowlist)\n  //   wall.getComments \u2014 PUBLIC POST comments (post-URL allowlist) \u2014 where consumer demand actually lives\n  // Enabling live requires ALL of: explicit operator approval (token), a non-empty allowlist for the chosen\n  // method(s), a VK API credential bound in n8n (token NEVER in this file), and enabling the disabled HTTP node.\n  // Hard scope: PUBLIC groups/posts/comments ONLY \u2014 no private messages, no closed groups, no member extraction,\n  // no hidden contacts, no auto-outreach, no mass people lists (aggregate author counts only).\n  live_transport:'vk_api',\n  live_methods:['wall.get','wall.getComments'],\n  live_approval_token:'',\n  live_group_allowlist:[],          // public group screen names / URLs (for wall.get)\n  live_post_allowlist:[],           // public post URLs e.g. https://vk.com/wall-111222_301 (for wall.getComments)\n  live_max_items_per_group:10,\n  live_requires_operator_approval:true,\n  platform:'vk',\n  source_type_post:'social_post',\n  source_type_comment:'social_comment',\n  requested_by:'operator',\n  request_type:'social_source_discovery',\n  region:'\u041c\u043e\u0441\u043a\u0432\u0430/\u041c\u041e',\n  service_focus:'credit_broker',\n  group_allowlist:[\n    'kredity_msk_fixture',\n    'biznes_finansy_fixture',\n    'uslugi_msk_fixture'\n  ],\n  pipeline_limit:12,\n  // --- MONITORED VK GROUPS (Stage C.1, DEC-141): group -> recent posts -> RELEVANT posts -> PUBLIC comments.\n  // STAGED/INERT: monitored_mode=false -> live two-stage HTTP placeholders stay DISABLED (no network).\n  // monitored_fixture_mode=true runs a deterministic $0 SIMULATION (no VK call). PUBLIC data only: no private\n  // messages, no closed groups, no member/follower extraction, no hidden/inferred contacts, no auto-outreach.\n  // Real production groups are NEVER committed here \u2014 operator fills monitored_groups per the VK runbook.\n  monitored_mode:false,\n  monitored_fixture_mode:false,\n  monitored_groups:[],            // [{screen_name, category:'competitor|finance_community|city_community|entrepreneur_community', enabled, region, niche_scope, post_lookback_days, max_posts_per_group, max_relevant_posts, max_comments_per_post}]\n  monitored_max_groups_per_run:5,\n  monitored_max_posts_per_group:10,\n  monitored_max_relevant_posts:5,\n  monitored_max_comments_per_post:20,\n  monitored_max_total_comments:100,\n  monitored_post_lookback_days:14,\n  monitored_request_timeout_ms:15000,\n  monitored_max_retries:2,\n  monitored_backoff_ms:1500,\n  approval_status_for_unique:'new',\n  write_duplicate_audit:true,\n  hard_skip_debug_audit:false,\n  duplicate_next_action:'monitor_duplicate',\n  spreadsheet_id_placeholder:'PASTE_SPREADSHEET_ID',\n  agent_request_id:'wf13_req_'+stamp,\n  run_id:'wf13_'+stamp,\n  created_at:now\n}}];\n"
      },
      "id": "wf13-config",
      "name": "Set Connector Config",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -200,
        560
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "wf13-if-fixture",
              "leftValue": "={{ $json.fixture_mode }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "wf13-if",
      "name": "IF fixture_mode?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        20,
        560
      ]
    },
    {
      "parameters": {
        "jsCode": "// Fixture VK PUBLIC group posts/comments (what a guarded VK API fetch would yield). $0, no network.\n// SYNTHETIC TEST DATA ONLY: group names carry _fixture; phones use the non-routable +7 000 prefix; profiles are\n// synthetic. The mix exercises the Stage 3.5 Lead Scout path end-to-end: consumer demand comments (high intent w/\n// synthetic username, high intent w/ synthetic phone, question w/o contact, complaint/fraud-fear, business finance),\n// plus negatives that must NOT become leads (competitor ad post, market-news post, hard-negative B2B service),\n// plus an in-batch duplicate. author_profile_public marks whether the author profile URL is public \u2014 profile_url is\n// recorded ONLY when public; never reconstructed; NEVER used for outreach.\nconst items=[\n { group:'kredity_msk_fixture', group_title:'\u041a\u0440\u0435\u0434\u0438\u0442\u044b \u041c\u043e\u0441\u043a\u0432\u0430 (fixture)', item_type:'post', item_id:'201', comment_id:'',\n   item_url:'https://vk.com/wall-111222_201', author_handle:'id_broker_msk_fixture', author_name:'\u041a\u0440\u0435\u0434\u0438\u0442\u043d\u044b\u0439 \u0411\u0440\u043e\u043a\u0435\u0440 \u041c\u0421\u041a (fixture)', author_profile_public:true,\n   published_at:'2026-06-14T12:10:00+03:00',\n   text:'\u041a\u0440\u0435\u0434\u0438\u0442\u043d\u044b\u0439 \u0431\u0440\u043e\u043a\u0435\u0440: \u043f\u043e\u043c\u043e\u0449\u044c \u0432 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043a\u0440\u0435\u0434\u0438\u0442\u0430 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u043e\u0432, \u0441 \u043f\u043b\u043e\u0445\u043e\u0439 \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439. \u0411\u0435\u0437 \u043f\u0440\u0435\u0434\u043e\u043f\u043b\u0430\u0442\u044b, \u043e\u043f\u043b\u0430\u0442\u0430 \u0437\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u041c\u043e\u0441\u043a\u0432\u0430 \u0438 \u041c\u041e. \u0422\u0435\u043b: +7 000 000-00-09' },\n { group:'kredity_msk_fixture', group_title:'\u041a\u0440\u0435\u0434\u0438\u0442\u044b \u041c\u043e\u0441\u043a\u0432\u0430 (fixture)', item_type:'comment', item_id:'201', comment_id:'2011',\n   item_url:'https://vk.com/wall-111222_201?reply=2011', author_handle:'id_user_synthetic_1', author_name:'\u0418\u0433\u043e\u0440\u044c (fixture)', author_profile_public:true,\n   published_at:'2026-06-14T13:45:00+03:00',\n   text:'\u0421\u0440\u043e\u0447\u043d\u043e \u043d\u0443\u0436\u0435\u043d \u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u0430 \u0434\u0432\u0443\u0445 \u0431\u0430\u043d\u043a\u043e\u0432, \u043f\u043b\u043e\u0445\u0430\u044f \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f. \u041a\u0442\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u043c\u043e\u0433? \u041f\u0438\u0448\u0438\u0442\u0435 @synthetic_lead_1' },\n { group:'kredity_msk_fixture', group_title:'\u041a\u0440\u0435\u0434\u0438\u0442\u044b \u041c\u043e\u0441\u043a\u0432\u0430 (fixture)', item_type:'comment', item_id:'201', comment_id:'2012',\n   item_url:'https://vk.com/wall-111222_201?reply=2012', author_handle:'id_user_synthetic_2', author_name:'\u041c\u0430\u0440\u0438\u043d\u0430 (fixture)', author_profile_public:true,\n   published_at:'2026-06-14T14:02:00+03:00',\n   text:'\u041d\u0443\u0436\u043d\u044b \u0434\u0435\u043d\u044c\u0433\u0438 \u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433 \u041f\u0422\u0421 \u0441\u0440\u043e\u0447\u043d\u043e, \u0438\u0449\u0443 \u0431\u0440\u043e\u043a\u0435\u0440\u0430 \u0432 \u041c\u043e\u0441\u043a\u0432\u0435. \u041c\u043e\u0439 \u0442\u0435\u043b\u0435\u0444\u043e\u043d +7 000 000-00-01, \u043f\u0435\u0440\u0435\u0437\u0432\u043e\u043d\u0438\u0442\u0435 \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430' },\n { group:'kredity_msk_fixture', group_title:'\u041a\u0440\u0435\u0434\u0438\u0442\u044b \u041c\u043e\u0441\u043a\u0432\u0430 (fixture)', item_type:'comment', item_id:'202', comment_id:'2021',\n   item_url:'https://vk.com/wall-111222_202?reply=2021', author_handle:'id_user_synthetic_3', author_name:'', author_profile_public:false,\n   published_at:'2026-06-13T09:00:00+03:00',\n   text:'\u041f\u043e\u0434\u0441\u043a\u0430\u0436\u0438\u0442\u0435, \u043a \u043a\u043e\u043c\u0443 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043f\u043b\u043e\u0445\u043e\u0439 \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0438? \u0421\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u044b\u0447\u043d\u043e \u0443 \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u0432?' },\n { group:'kredity_msk_fixture', group_title:'\u041a\u0440\u0435\u0434\u0438\u0442\u044b \u041c\u043e\u0441\u043a\u0432\u0430 (fixture)', item_type:'comment', item_id:'202', comment_id:'2022',\n   item_url:'https://vk.com/wall-111222_202?reply=2022', author_handle:'id_user_synthetic_4', author_name:'\u0410\u043d\u043e\u043d\u0438\u043c (fixture)', author_profile_public:true,\n   published_at:'2026-06-13T12:00:00+03:00',\n   text:'\u042d\u0442\u0438 \u0431\u0440\u043e\u043a\u0435\u0440\u044b \u043c\u043e\u0448\u0435\u043d\u043d\u0438\u043a\u0438 \u2014 \u0432\u0437\u044f\u043b\u0438 \u043f\u0440\u0435\u0434\u043e\u043f\u043b\u0430\u0442\u0443 \u0437\u0430 \u043a\u0440\u0435\u0434\u0438\u0442 \u0438 \u043f\u0440\u043e\u043f\u0430\u043b\u0438, \u043e\u0431\u043c\u0430\u043d\u0443\u043b\u0438. \u0411\u043e\u044e\u0441\u044c \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u043a\u043e\u043c\u0443-\u043b\u0438\u0431\u043e.' },\n { group:'biznes_finansy_fixture', group_title:'\u0411\u0438\u0437\u043d\u0435\u0441 \u0438 \u0444\u0438\u043d\u0430\u043d\u0441\u044b (fixture)', item_type:'comment', item_id:'88', comment_id:'881',\n   item_url:'https://vk.com/wall-333444_88?reply=881', author_handle:'id_user_synthetic_5', author_name:'\u0418\u041f \u0421\u0438\u043d\u0442\u0435\u0442\u0438\u043a (fixture)', author_profile_public:true,\n   published_at:'2026-06-14T08:00:00+03:00',\n   text:'\u041d\u0443\u0436\u0435\u043d \u043a\u0440\u0435\u0434\u0438\u0442 \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430 (\u041e\u041e\u041e), \u043e\u0431\u043e\u0440\u043e\u0442\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430, \u0438 \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u0430\u044f \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u044f \u043f\u043e\u0434 \u0442\u0435\u043d\u0434\u0435\u0440. \u0413\u0434\u0435 \u043b\u0443\u0447\u0448\u0435 \u0432\u0437\u044f\u0442\u044c?' },\n { group:'biznes_finansy_fixture', group_title:'\u0411\u0438\u0437\u043d\u0435\u0441 \u0438 \u0444\u0438\u043d\u0430\u043d\u0441\u044b (fixture)', item_type:'post', item_id:'88', comment_id:'',\n   item_url:'https://vk.com/wall-333444_88', author_handle:'id_fin_editor_fixture', author_name:'\u0420\u0435\u0434\u0430\u043a\u0446\u0438\u044f (fixture)', author_profile_public:false,\n   published_at:'2026-06-12T09:30:00+03:00',\n   text:'\u0411\u0430\u043d\u043a\u0438 \u0443\u0436\u0435\u0441\u0442\u043e\u0447\u0438\u043b\u0438 \u0441\u043a\u043e\u0440\u0438\u043d\u0433: \u043e\u0442\u043a\u0430\u0437\u043e\u0432 \u043f\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u043c \u043a\u0440\u0435\u0434\u0438\u0442\u0430\u043c \u0441\u0442\u0430\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u0435. \u041e\u0431\u0437\u043e\u0440 \u0440\u044b\u043d\u043a\u0430 \u043a\u0440\u0435\u0434\u0438\u0442\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430.' },\n { group:'uslugi_msk_fixture', group_title:'\u0423\u0441\u043b\u0443\u0433\u0438 \u041c\u043e\u0441\u043a\u0432\u0430 (fixture)', item_type:'post', item_id:'55', comment_id:'',\n   item_url:'https://vk.com/wall-555666_55', author_handle:'id_reg_firm_fixture', author_name:'\u0420\u0435\u0433\u0424\u0438\u0440\u043c\u0430 (fixture)', author_profile_public:true,\n   published_at:'2026-06-11T10:00:00+03:00',\n   text:'\u042e\u0440\u0438\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 \u0434\u043b\u044f \u041e\u041e\u041e \u043e\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0438\u043a\u0430, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u041e\u041e\u041e \u0438 \u0418\u041f \u043f\u043e\u0434 \u043a\u043b\u044e\u0447, \u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440\u0441\u043a\u043e\u0435 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u0435.' },\n { group:'kredity_msk_fixture', group_title:'\u041a\u0440\u0435\u0434\u0438\u0442\u044b \u041c\u043e\u0441\u043a\u0432\u0430 (fixture)', item_type:'comment', item_id:'201', comment_id:'2011',\n   item_url:'https://vk.com/wall-111222_201?reply=2011', author_handle:'id_user_synthetic_1', author_name:'\u0418\u0433\u043e\u0440\u044c (fixture)', author_profile_public:true,\n   published_at:'2026-06-14T13:45:00+03:00',\n   text:'\u0421\u0440\u043e\u0447\u043d\u043e \u043d\u0443\u0436\u0435\u043d \u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u0430 \u0434\u0432\u0443\u0445 \u0431\u0430\u043d\u043a\u043e\u0432, \u043f\u043b\u043e\u0445\u0430\u044f \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f. \u041a\u0442\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u043c\u043e\u0433? \u041f\u0438\u0448\u0438\u0442\u0435 @synthetic_lead_1' }\n];\nreturn items.map(p=>({json:p}));\n"
      },
      "id": "wf13-fixture",
      "name": "Build Fixture VK Group Items",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        440
      ]
    },
    {
      "parameters": {
        "jsCode": "// LIVE VK APPROVAL GATE v0.3 (DEC-125/138) \u2014 fires on fixture_mode=false. INERT BY DEFAULT: throws unless the\n// operator has explicitly armed the run. Even when armed, the downstream HTTP node ships DISABLED with no\n// credential, so no network call can happen without a second deliberate operator action.\n// Supports BOTH public methods: wall.get (public group walls) and wall.getComments (PUBLIC POST comments \u2014 where\n// consumer demand lives). Hard scope (CONTACT_AND_OUTREACH_POLICY): PUBLIC VK groups/posts/comments ONLY \u2014 no\n// private messages, no closed groups, no member extraction, no hidden contacts, no auto-outreach, no people lists.\nfunction str(v){return v==null?'':String(v).trim();}\nconst cfg=$('Set Connector Config').first().json;\nconst token=str(cfg.live_approval_token);\nconst methods=Array.isArray(cfg.live_methods)?cfg.live_methods.map(str).filter(Boolean):['wall.get'];\nconst groups=Array.isArray(cfg.live_group_allowlist)?cfg.live_group_allowlist.map(g=>str(g)).filter(Boolean):[];\nconst posts=Array.isArray(cfg.live_post_allowlist)?cfg.live_post_allowlist.map(p=>str(p)).filter(Boolean):[];\nconst maxItems=Math.min(Number(cfg.live_max_items_per_group)||10,10);\nif(token!=='I_APPROVE_LIVE_VK_PUBLIC_DISCUSSION'){\n  throw new Error('WF13 live gate: operator approval token missing. Live VK public discussion fetch requires explicit operator approval: set live_approval_token=I_APPROVE_LIVE_VK_PUBLIC_DISCUSSION, fill live_group_allowlist (public groups for wall.get) and/or live_post_allowlist (public post URLs for wall.getComments), bind a VK API credential in n8n, then ENABLE the disabled HTTP node. Default run stays fixture-only ($0). See docs/N8N_WORKFLOW_13_PUBLIC_DISCUSSION_OR_REVIEWS_CONNECTOR_RU.md.');\n}\nif(!groups.length&&!posts.length){ throw new Error('WF13 live gate: both live_group_allowlist and live_post_allowlist are empty \u2014 allowlist-only operation, no discovery crawling.'); }\n// reject anything that is not a public group/post reference: invite links, private/closed markers, phone-like ids\nconst badG=groups.filter(g=>/join|invite|im\\?sel|write\\d|@|\\s/i.test(g)||g.charAt(0)==='+');\nif(badG.length){ throw new Error('WF13 live gate: rejected non-public-group entries (invite links / private chats are forbidden): '+badG.join(', ')); }\nconst out=[];\nif(methods.indexOf('wall.get')>=0){\n  for(const g of groups){\n    const screen=g.replace(/^https?:\\/\\/(www\\.)?vk\\.com\\//i,'').replace(/[\\/?#].*$/,'');\n    out.push({ json: { method:'wall.get', fetch_url:'https://api.vk.com/method/wall.get', screen_name:screen, owner_id:'', post_id:'', max_items:maxItems, api_version:'5.199', live_transport:'vk_api' } });\n  }\n}\nif(methods.indexOf('wall.getComments')>=0){\n  for(const u of posts){\n    const m=str(u).match(/wall(-?\\d+)_(\\d+)/);\n    if(!m){ throw new Error('WF13 live gate: live_post_allowlist entry is not a public wall post URL (expected .../wall-<owner>_<post>): '+u); }\n    out.push({ json: { method:'wall.getComments', fetch_url:'https://api.vk.com/method/wall.getComments', screen_name:'', owner_id:m[1], post_id:m[2], max_items:maxItems, api_version:'5.199', live_transport:'vk_api' } });\n  }\n}\nif(!out.length){ throw new Error('WF13 live gate: no live targets produced for the selected live_methods ('+methods.join(', ')+').'); }\nreturn out;\n"
      },
      "id": "wf13-guard",
      "name": "LIVE VK Approval Gate",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        700
      ]
    },
    {
      "parameters": {
        "jsCode": "// Normalize VK public posts/comments into the WF09/WF11-compatible record shape. Deterministic, $0.\n// Audience focus (DEC-121): questions/objections from public discussions become question_objection\n// records feeding WF08 -> WF10 audience_activity_signals. Contact policy (DEC-097/098/114): contact_public\n// ONLY when visible verbatim in the public text; author profile_url ONLY when the profile is public;\n// nothing reconstructed; no outreach \u2014 default manual_review.\nfunction str(v){return v==null?'':String(v).trim();}\nfunction low(v){return str(v).toLowerCase();}\nfunction cut(s,n){s=str(s);return s.length>n?s.slice(0,n):s;}\nfunction hashText(s){s=str(s);let h=5381;for(let i=0;i<s.length;i++){h=((h<<5)+h+s.charCodeAt(i))>>>0;}return ('00000000'+h.toString(16)).slice(-8);}\nfunction canonUrl(u){u=str(u);return u.replace(/[?#].*$/,'').replace(/\\/+$/,'');}\nconst cfg=$('Set Connector Config').first().json;\nconst items=$input.all().map(i=>i.json);\n// niche vocabulary v0.1 hardcoded (credit_brokerage) \u2014 migrates to niche packs (DEC-100)\nconst STRONG=['\u043a\u0440\u0435\u0434\u0438\u0442\u043d\u044b\u0439 \u0431\u0440\u043e\u043a\u0435\u0440','\u0438\u043f\u043e\u0442\u0435\u0447\u043d\u044b\u0439 \u0431\u0440\u043e\u043a\u0435\u0440','\u043f\u043e\u043c\u043e\u0449\u044c \u0432 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u043a\u0440\u0435\u0434\u0438\u0442\u0430','\u043f\u043e\u043c\u043e\u0449\u044c \u0441 \u043a\u0440\u0435\u0434\u0438\u0442\u043e\u043c','\u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u043e\u0432','\u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u043e\u0432','\u043f\u043b\u043e\u0445\u043e\u0439 \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0435\u0439','\u043f\u043b\u043e\u0445\u0430\u044f \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f','\u043a\u0440\u0435\u0434\u0438\u0442 \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430','\u043e\u0431\u043e\u0440\u043e\u0442\u043d\u044b\u0435','\u0442\u0435\u043d\u0434\u0435\u0440\u043d\u044b\u0435 \u0437\u0430\u0439\u043c','\u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u0438\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0438','\u0440\u0435\u0444\u0438\u043d\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435','\u0441\u043d\u0438\u0436\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0432\u043a\u0438','\u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u0435 \u043a\u0440\u0435\u0434\u0438\u0442\u0430','\u043f\u043e\u0434\u0431\u043e\u0440 \u0431\u0430\u043d\u043a\u0430'];\nconst WEAK=['\u043a\u0440\u0435\u0434\u0438\u0442','\u0437\u0430\u0439\u043c','\u0431\u0430\u043d\u043a','\u043e\u0442\u043a\u0430\u0437','\u0441\u043a\u043e\u0440\u0438\u043d\u0433','\u0441\u0442\u0430\u0432\u043a','\u0437\u0430\u0451\u043c\u0449\u0438\u043a','\u0438\u043f\u043e\u0442\u0435\u043a','\u0444\u0438\u043d\u0430\u043d\u0441','\u0431\u0440\u043e\u043a\u0435\u0440','\u043f\u0440\u0435\u0434\u043e\u043f\u043b\u0430\u0442','\u043f\u0440\u043e\u0441\u0440\u043e\u0447\u043a'];\nconst HARD_NEG=['\u044e\u0440\u0438\u0434\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u0434\u0440\u0435\u0441','\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043e\u043e\u043e','\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0438\u043f','\u0431\u0443\u0445\u0433\u0430\u043b\u0442\u0435\u0440','\u044d\u043a\u0432\u0430\u0439\u0440\u0438\u043d\u0433','pos-\u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b','\u043a\u0430\u0441\u0441\u0430','\u043f\u0435\u0447\u0430\u0442\u044c \u0438 \u0448\u0442\u0430\u043c\u043f','\u044d\u0446\u043f','\u0430\u0440\u0435\u043d\u0434\u0430 \u043e\u0444\u0438\u0441\u0430','\u043a\u043e\u0432\u043e\u0440\u043a\u0438\u043d\u0433'];\nconst QUESTION=['\u043f\u043e\u0434\u0441\u043a\u0430\u0436\u0438\u0442\u0435','\u043f\u043e\u0441\u043e\u0432\u0435\u0442\u0443\u0439\u0442\u0435','\u043a\u0442\u043e \u0431\u0440\u0430\u043b','\u043a\u0442\u043e \u043e\u0431\u0440\u0430\u0449\u0430\u043b\u0441\u044f','\u043a \u043a\u043e\u043c\u0443 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f','\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e \u0441\u0442\u043e\u0438\u0442','\u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c','\u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c','?'];\nconst OBJECTION=['\u043c\u043e\u0448\u0435\u043d\u043d\u0438\u043a','\u043e\u0431\u043c\u0430\u043d','\u043a\u0438\u0434\u0430\u043b','\u043f\u0440\u0435\u0434\u043e\u043f\u043b\u0430\u0442\u0443 \u0438 \u043f\u0440\u043e\u043f\u0430\u0434\u0430','\u043d\u0435 \u0432\u0435\u0440\u044e','\u0440\u0430\u0437\u0432\u043e\u0434','\u0431\u043e\u044e\u0441\u044c'];\n// consumer DEMAND markers (Stage 3.5): a member publicly asking/needing -> audience lead signal (not a question shape)\nconst DEMAND=['\u043d\u0443\u0436\u0435\u043d \u043a\u0440\u0435\u0434\u0438\u0442','\u043d\u0443\u0436\u0435\u043d \u0437\u0430\u0439\u043c','\u043d\u0443\u0436\u043d\u0430 \u0438\u043f\u043e\u0442\u0435\u043a','\u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0444\u0438\u043d\u0430\u043d\u0441','\u043d\u0443\u0436\u043d\u044b \u0434\u0435\u043d\u044c\u0433\u0438','\u0438\u0449\u0443 \u0431\u0440\u043e\u043a\u0435\u0440\u0430','\u0438\u0449\u0443 \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u043e\u0433\u043e \u0431\u0440\u043e\u043a\u0435\u0440\u0430','\u043f\u043e\u043c\u043e\u0433\u0438\u0442\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c','\u043f\u043e\u043c\u043e\u0433\u0438\u0442\u0435 \u0432\u0437\u044f\u0442\u044c','\u0445\u043e\u0447\u0443 \u0432\u0437\u044f\u0442\u044c \u043a\u0440\u0435\u0434\u0438\u0442','\u0434\u0435\u043d\u044c\u0433\u0438 \u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433','\u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433 \u043f\u0442\u0441','\u043a\u0440\u0435\u0434\u0438\u0442 \u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430','\u043d\u0443\u0436\u043d\u0430 \u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a\u0430\u044f \u0433\u0430\u0440\u0430\u043d\u0442\u0438','\u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437'];\nconst KW=[['\u043a\u0440\u0435\u0434\u0438\u0442\u043d\u044b\u0439 \u0431\u0440\u043e\u043a\u0435\u0440','\u043a\u0440\u0435\u0434\u0438\u0442\u043d\u044b\u0439 \u0431\u0440\u043e\u043a\u0435\u0440'],['\u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u043e\u0432','\u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u043e\u0432'],['\u043f\u043b\u043e\u0445','\u043f\u043b\u043e\u0445\u0430\u044f \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f'],['\u0431\u0435\u0437 \u043f\u0440\u0435\u0434\u043e\u043f\u043b\u0430\u0442\u044b','\u0431\u0435\u0437 \u043f\u0440\u0435\u0434\u043e\u043f\u043b\u0430\u0442\u044b'],['\u043e\u043f\u043b\u0430\u0442\u0430 \u0437\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442','\u043e\u043f\u043b\u0430\u0442\u0430 \u0437\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442'],['\u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430','\u0431\u0438\u0437\u043d\u0435\u0441-\u043a\u0440\u0435\u0434\u0438\u0442'],['\u0440\u0435\u0444\u0438\u043d\u0430\u043d\u0441\u0438\u0440','\u0440\u0435\u0444\u0438\u043d\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435'],['\u043f\u0440\u043e\u0441\u0440\u043e\u0447\u043a','\u043f\u0440\u043e\u0441\u0440\u043e\u0447\u043a\u0438'],['\u043f\u0440\u0435\u0434\u043e\u043f\u043b\u0430\u0442','\u043f\u0440\u0435\u0434\u043e\u043f\u043b\u0430\u0442\u0430 (\u0434\u043e\u0432\u0435\u0440\u0438\u0435)'],['\u043c\u043e\u0448\u0435\u043d\u043d\u0438\u043a','\u043d\u0435\u0434\u043e\u0432\u0435\u0440\u0438\u0435 \u043a \u0431\u0440\u043e\u043a\u0435\u0440\u0430\u043c'],['\u043e\u0442\u043a\u0430\u0437','\u043e\u0442\u043a\u0430\u0437\u044b \u0431\u0430\u043d\u043a\u043e\u0432']];\n// Defect C: probable_need must reflect ACTUAL evidence \u2014 never inherit a refusal hint without refusal evidence.\nfunction probableNeed(blob,rth){\n  if(rth!=='question_objection')return '';\n  if(blob.indexOf('\u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437')>=0||blob.indexOf('\u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0438')>=0||blob.indexOf('\u0431\u0430\u043d\u043a \u043e\u0442\u043a\u0430\u0437')>=0||blob.indexOf('\u043e\u0442\u043a\u0430\u0437 \u0431\u0430\u043d\u043a')>=0)return '\u043f\u043e\u043c\u043e\u0449\u044c \u0441 \u043a\u0440\u0435\u0434\u0438\u0442\u043e\u043c \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u043e\u0432 \u0431\u0430\u043d\u043a\u043e\u0432';\n  if(blob.indexOf('\u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433 \u043f\u0442\u0441')>=0||blob.indexOf('\u043f\u0442\u0441')>=0||blob.indexOf('\u0437\u0430\u043b\u043e\u0433 \u0430\u0432\u0442\u043e')>=0)return '\u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433 \u041f\u0422\u0421';\n  if(blob.indexOf('\u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433 \u043d\u0435\u0434\u0432\u0438\u0436')>=0||blob.indexOf('\u0437\u0430\u043b\u043e\u0433 \u043d\u0435\u0434\u0432\u0438\u0436')>=0)return '\u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433 \u043d\u0435\u0434\u0432\u0438\u0436\u0438\u043c\u043e\u0441\u0442\u0438';\n  if(blob.indexOf('\u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430')>=0||blob.indexOf('\u043e\u0431\u043e\u0440\u043e\u0442\u043d')>=0||blob.indexOf('\u0442\u0435\u043d\u0434\u0435\u0440')>=0||blob.indexOf('\u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a \u0433\u0430\u0440\u0430\u043d\u0442\u0438')>=0||blob.indexOf('\u0434\u043b\u044f \u043e\u043e\u043e')>=0||blob.indexOf('\u0434\u043b\u044f \u0438\u043f')>=0)return '\u0444\u0438\u043d\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0438\u0437\u043d\u0435\u0441\u0430 (\u043e\u0431\u043e\u0440\u043e\u0442\u043d\u044b\u0435/\u0433\u0430\u0440\u0430\u043d\u0442\u0438\u044f/\u0442\u0435\u043d\u0434\u0435\u0440)';\n  if(blob.indexOf('\u0438\u043f\u043e\u0442\u0435\u043a')>=0)return '\u0438\u043f\u043e\u0442\u0435\u043a\u0430';\n  if(blob.indexOf('\u0440\u0435\u0444\u0438\u043d\u0430\u043d\u0441')>=0||blob.indexOf('\u0441\u043d\u0438\u0437\u0438\u0442\u044c \u0441\u0442\u0430\u0432\u043a')>=0)return '\u0440\u0435\u0444\u0438\u043d\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435';\n  if(blob.indexOf('\u043f\u043b\u043e\u0445\u0430\u044f \u043a\u0440\u0435\u0434\u0438\u0442\u043d')>=0||blob.indexOf('\u043f\u043b\u043e\u0445\u043e\u0439 \u043a\u0440\u0435\u0434\u0438\u0442\u043d')>=0||blob.indexOf('\u043f\u043b\u043e\u0445\u0430\u044f \u043a\u0438')>=0)return '\u043a\u0440\u0435\u0434\u0438\u0442 \u043f\u0440\u0438 \u043f\u043b\u043e\u0445\u043e\u0439 \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u043e\u0439 \u0438\u0441\u0442\u043e\u0440\u0438\u0438';\n  return '';\n}\nconst out=[];\nfor(const p of items){\n  const isComment=(low(p.item_type)==='comment');\n  const text=str(p.text);\n  const blob=low(text)+' '+low(p.group_title);\n  const valid=!!(str(p.group)&&str(p.item_id)&&text.length>=30);\n  const strongHit=STRONG.filter(t=>blob.indexOf(t)>=0);\n  const weakHit=WEAK.filter(t=>blob.indexOf(t)>=0);\n  const negHit=HARD_NEG.filter(t=>blob.indexOf(t)>=0);\n  const qHit=QUESTION.filter(t=>blob.indexOf(t)>=0);\n  const objHit=OBJECTION.filter(t=>blob.indexOf(t)>=0);\n  const demHit=DEMAND.filter(t=>blob.indexOf(t)>=0);\n  let record_type_hint='irrelevant';let touchpoint_type='irrelevant_source';let predicted_entity_type='irrelevant';let predicted_route='skipped_log';\n  let lead_intent='none';let confidence=10;let hard_skip=false;let relevance_reason='';\n  const looksAd=/\u0442\u0435\u043b[:.]|\\+7|\u0431\u0435\u0437 \u043f\u0440\u0435\u0434\u043e\u043f\u043b\u0430\u0442\u044b|\u043e\u043f\u043b\u0430\u0442\u0430 \u0437\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442|\u043f\u043e\u0434 \u043a\u043b\u044e\u0447/i.test(text)&&!isComment;\n  if(!valid){ relevance_reason='invalid: missing group/item_id or text<30'; }\n  else if(negHit.length&&!strongHit.length){ hard_skip=true; relevance_reason='hard negative: '+negHit.join(', '); }\n  else if(strongHit.length&&looksAd){ record_type_hint='competitor_activity';touchpoint_type='competitor_content_post';predicted_entity_type='competitor';predicted_route='monitor_queue';confidence=70;relevance_reason='strong competitor ad: '+strongHit.slice(0,4).join(', '); }\n  else if((demHit.length||qHit.length||objHit.length)&&(strongHit.length||weakHit.length>=2||demHit.length)){ record_type_hint='question_objection';touchpoint_type='forum_discussion';predicted_entity_type='lead_signal';predicted_route='review_queue';lead_intent=demHit.length?'high':(objHit.length&&!qHit.length?'low':'medium');confidence=demHit.length?65:(objHit.length&&!qHit.length?50:60);relevance_reason=(demHit.length?('demand: '+demHit.slice(0,3).join(', ')):'')+(qHit.length?((demHit.length?'; ':'')+'question: '+qHit.slice(0,3).join(', ')):'')+(objHit.length?(((demHit.length||qHit.length)?'; ':'')+'objection: '+objHit.slice(0,3).join(', ')):''); }\n  else if(strongHit.length){ record_type_hint='market_signal';predicted_entity_type='market_signal';touchpoint_type='forum_discussion';predicted_route='content_queue';confidence=50;relevance_reason='strong niche terms, no ad/question shape: '+strongHit.slice(0,4).join(', '); }\n  else if(weakHit.length>=2){ record_type_hint='market_signal';predicted_entity_type='market_signal';touchpoint_type='forum_discussion';predicted_route='content_queue';confidence=45;relevance_reason='weak finance: '+weakHit.slice(0,4).join(', '); }\n  else { hard_skip=true; relevance_reason='no niche evidence'; }\n  // VK comments are their own public touchpoint class (DEC-125): any business-relevant COMMENT row\n  // carries touchpoint_type=public_comment (posts keep competitor_content_post / forum_discussion).\n  if(isComment&&!hard_skip&&record_type_hint!=='irrelevant'){ touchpoint_type='public_comment'; }\n  // public contact: verbatim phone/@handle in the PUBLIC text only \u2014 never reconstructed (DEC-114 channel category).\n  let contact='';let contactChannel='';let contactFormat='';\n  const ph=text.match(/(?:\\+7|8)[\\s\\-(]*\\d{3}[\\s\\-)]*\\d{3}[\\s\\-]*\\d{2}[\\s\\-]*\\d{2}/);\n  const h=text.match(/@[a-zA-Z0-9_]{5,32}/);\n  if(ph){contact=ph[0];contactChannel='phone';contactFormat='phone';}\n  else if(h){contact=h[0];contactChannel='telegram';contactFormat='handle';}\n  const kws=[];const seen={};for(const k of KW){if(blob.indexOf(k[0])>=0&&!seen[k[1]]){seen[k[1]]=1;kws.push(k[1]);}}\n  let service='unknown';\n  if(blob.indexOf('\u0438\u043f\u043e\u0442\u0435\u043a')>=0||blob.indexOf('\u0440\u0435\u0444\u0438\u043d\u0430\u043d\u0441\u0438\u0440')>=0)service='mortgage_refinance';\n  else if(blob.indexOf('\u0434\u043b\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u0430')>=0||blob.indexOf('\u043e\u0431\u043e\u0440\u043e\u0442\u043d\u044b\u0435')>=0||blob.indexOf('\u0442\u0435\u043d\u0434\u0435\u0440')>=0||blob.indexOf('\u0431\u0430\u043d\u043a\u043e\u0432\u0441\u043a \u0433\u0430\u0440\u0430\u043d\u0442\u0438')>=0)service='business_credit';\n  else if(blob.indexOf('\u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433 \u043f\u0442\u0441')>=0||blob.indexOf('\u043f\u0442\u0441')>=0||blob.indexOf('\u0437\u0430\u043b\u043e\u0433 \u0430\u0432\u0442\u043e')>=0||blob.indexOf('\u043f\u043e\u0434 \u0437\u0430\u043b\u043e\u0433')>=0)service='pts_loan';\n  else if(blob.indexOf('\u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u043a\u0430\u0437\u043e\u0432')>=0||blob.indexOf('\u043e\u0442\u043a\u0430\u0437')>=0)service='credit_after_refusals';\n  if(blob.indexOf('\u043a\u0440\u0435\u0434\u0438\u0442\u043d\u044b\u0439 \u0431\u0440\u043e\u043a\u0435\u0440')>=0)service='credit_broker';\n  const canon=canonUrl(p.item_url)+(isComment?('#reply'+str(p.comment_id)):'');\n  const publicProfile=(p.author_profile_public===true);\n  out.push({ json: {\n    is_valid_listing:valid,\n    hard_skip:hard_skip,\n    relevance_reason:relevance_reason,\n    source_type:isComment?(str(cfg.source_type_comment)||'social_comment'):(str(cfg.source_type_post)||'social_post'),\n    platform:str(cfg.platform)||'vk',\n    source_url:'https://vk.com/'+str(p.group),\n    post_url:canon,\n    profile_url:publicProfile?('https://vk.com/'+str(p.author_handle)):'',\n    profile_name:str(p.author_name),\n    author_handle:str(p.author_handle),\n    author_key:str(p.author_handle)||str(p.author_name),\n    published_at:str(p.published_at),\n    region_hint:(blob.indexOf('\u043c\u043e\u0441\u043a\u0432')>=0||blob.indexOf(' \u043c\u043e')>=0?'\u041c\u043e\u0441\u043a\u0432\u0430/\u041c\u041e':''),\n    service_hint:service,\n    query:'allowlist:'+str(p.group),\n    text_context:isComment?('\u041e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u0435 \u0432 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435 VK '+str(p.group_title)+', \u043f\u043e\u0441\u0442 '+canonUrl(p.item_url)):cut(text,3500),\n    comment_text:isComment?cut(text,3500):'',\n    contact_public:contact,\n    contact_channel:contactChannel,\n    contact_format:contactFormat,\n    dedup_key:'vk::'+(isComment?'social_comment':'social_post')+'::'+canon,\n    text_hash:hashText(low(text)),\n    record_type_hint:record_type_hint,\n    touchpoint_type:touchpoint_type,\n    lead_intent_hint:lead_intent,\n    urgency_hint:'none',\n    interest_topic:(record_type_hint==='competitor_activity')?'competitor VK ad copy':(record_type_hint==='question_objection'?'audience pain / question':(record_type_hint==='market_signal'?'market context':'')),\n    probable_need:probableNeed(blob,record_type_hint),\n    competitor_related:(record_type_hint==='competitor_activity'),\n    competitor_name:(record_type_hint==='competitor_activity')?str(p.author_name):'',\n    semantic_keywords:kws.join(', '),\n    ad_channel_hint:'vk',\n    confidence_score:confidence,\n    lead_temperature:(record_type_hint==='question_objection'&&lead_intent==='medium')?'warm':'none',\n    next_action:(record_type_hint==='question_objection')?'investigate':'monitor',\n    responsible:'operator',\n    estimated_analysis_cost_usd:0,\n    manager_note:'',\n    predicted_route:predicted_route,\n    predicted_entity_type:predicted_entity_type,\n    contact_evidence_url:contact?canon:'',\n    notes:''\n  }});\n}\nreturn out;"
      },
      "id": "wf13-normalize",
      "name": "Normalize VK Items",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        440
      ]
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "documentId": {
          "__rl": true,
          "value": "PASTE_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "market_record_registry",
          "mode": "name"
        },
        "options": {}
      },
      "id": "wf13-read-reg",
      "name": "Read market_record_registry",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        680,
        440
      ],
      "alwaysOutputData": true,
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "jsCode": "// Dedup vs market_record_registry (dedup_key) + within batch. Mirrors WF09/WF11: invalid and\n// hard-skipped items never register, never count unique, never consume the pipeline cap.\nfunction str(v){return v==null?'':String(v).trim();}\nconst cfg=$('Set Connector Config').first().json;\nconst approvalUnique=str(cfg.approval_status_for_unique)||'new';\nconst dupNext=str(cfg.duplicate_next_action)||'monitor_duplicate';\nconst pipelineLimit=Number(cfg.pipeline_limit)||10;\nconst recs=$('Normalize VK Items').all().map(i=>i.json);\nlet reg=[];\ntry{reg=$('Read market_record_registry').all().map(i=>i.json).filter(Boolean);}catch(e){reg=[];}\nconst regSet=new Set(reg.map(r=>str(r&&r.dedup_key)).filter(Boolean));\nconst seen=new Set();\nconst out=[];\nlet acceptedCount=0;\nfor(const r of recs){\n  if(r.is_valid_listing===false){ out.push({ json: Object.assign({}, r, { dedup_status:'invalid', approval_status:'invalid', next_action:'ignore' }) }); continue; }\n  if(r.hard_skip===true){ out.push({ json: Object.assign({}, r, { dedup_status:'hard_skipped', approval_status:'skipped_irrelevant', next_action:'ignore' }) }); continue; }\n  if(acceptedCount>=pipelineLimit){ out.push({ json: Object.assign({}, r, { dedup_status:'over_pipeline_limit', approval_status:'skipped', next_action:'ignore' }) }); continue; }\n  acceptedCount++;\n  const key=str(r.dedup_key);\n  let dedup_status='unique';let approval_status=approvalUnique;let next_action=str(r.next_action);\n  if(key&&regSet.has(key)){ dedup_status='duplicate_in_registry';approval_status='duplicate';next_action=dupNext; }\n  else if(key&&seen.has(key)){ dedup_status='duplicate_in_batch';approval_status='duplicate';next_action=dupNext; }\n  else { dedup_status='unique';if(key)seen.add(key); }\n  out.push({ json: Object.assign({}, r, { dedup_status:dedup_status, approval_status:approval_status, next_action:next_action }) });\n}\nreturn out;"
      },
      "id": "wf13-dedup",
      "name": "Deduplicate Items",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        440
      ]
    },
    {
      "parameters": {
        "jsCode": "// Build raw_market_records rows (exactly 40 columns, matching WF07/WF09/WF11 schema). No external calls.\nfunction str(v){return v==null?'':String(v).trim();}\n// Sheets formula-injection / #ERROR! fix (DEC-124): values starting with + or = are parsed as formulas\n// by Google Sheets (USER_ENTERED) \u2014 '+7 ...' phones become #ERROR!. A leading apostrophe forces text.\nfunction sheetsSafeText(v){v=str(v);return /^[+=]/.test(v)?(\"'\"+v):v;}\nfunction moscowIsoNow(){var m=new Date(Date.now()+10800000);return m.toISOString().replace('Z','+03:00');}\nfunction moscowStamp(){var z=function(n){return String(n).padStart(2,'0');};var m=new Date(Date.now()+10800000);return m.getUTCFullYear()+z(m.getUTCMonth()+1)+z(m.getUTCDate())+'_'+z(m.getUTCHours())+z(m.getUTCMinutes())+z(m.getUTCSeconds());}\nconst cfg=$('Set Connector Config').first().json;\nconst reqId=str(cfg.agent_request_id);\nconst created=str(cfg.created_at);\nconst stamp=str(cfg.run_id).replace(/^wf13_/,'')||moscowStamp();\nconst writeDupAudit=(cfg.write_duplicate_audit===true||str(cfg.write_duplicate_audit).toLowerCase()==='true');\nconst hardDebug=(cfg.hard_skip_debug_audit===true||str(cfg.hard_skip_debug_audit).toLowerCase()==='true');\nconst recs=$('Deduplicate Items').all().map(i=>i.json);\nconst out=[];let idx=0;\nfor(const r of recs){\n  idx++;\n  const ds0=str(r.dedup_status);\n  if(ds0==='invalid'||ds0==='over_pipeline_limit')continue;\n  if(ds0==='hard_skipped'&&!hardDebug)continue;\n  if(!writeDupAudit && ds0!=='unique')continue;\n  let notes='stage_3_source_foundation_vk_public_discussion';\n  if(str(r.contact_public)){ notes+='; contact_format='+(str(r.contact_format)||'unknown')+'; contact_source_url='+str(r.contact_evidence_url)+'; contact_use_policy=manual_review (CONTACT_AND_OUTREACH_POLICY)'; }\n  out.push({ json: {\n    record_id:'wf13_rec_'+stamp+'_'+idx,\n    agent_request_id:reqId,\nsource_run_id:str(cfg.run_id)||reqId,\ndata_mode:str(cfg.data_mode)||\"live\",\nquality_status:\"healthy\",\nreport_eligible:true,\nreview_status:\"confirmed\",\nquality_flags:\"\",\n    created_at:created,\n    source_type:str(r.source_type),\n    platform:str(r.platform),\n    source_url:str(r.source_url),\n    post_url:str(r.post_url),\n    profile_url:str(r.profile_url),\n    profile_name:str(r.profile_name),\n    author_handle:str(r.author_handle),\n    published_at:str(r.published_at),\n    region_hint:str(r.region_hint),\n    service_hint:str(r.service_hint),\n    query:str(r.query),\n    text_context:str(r.text_context),\n    comment_text:str(r.comment_text),\n    contact_public:sheetsSafeText(r.contact_public),\n    contact_channel:str(r.contact_channel),\n    dedup_key:str(r.dedup_key),\n    record_type_hint:str(r.record_type_hint),\n    touchpoint_type:str(r.touchpoint_type),\n    lead_intent_hint:str(r.lead_intent_hint),\n    urgency_hint:str(r.urgency_hint),\n    interest_topic:str(r.interest_topic),\n    probable_need:str(r.probable_need),\n    competitor_related:(r.competitor_related===true||str(r.competitor_related).toLowerCase()==='true'),\n    competitor_name:str(r.competitor_name),\n    semantic_keywords:str(r.semantic_keywords),\n    ad_channel_hint:str(r.ad_channel_hint),\n    confidence_score:Number(r.confidence_score)||0,\n    lead_temperature:str(r.lead_temperature),\n    next_action:str(r.next_action),\n    responsible:str(r.responsible),\n    dedup_status:str(r.dedup_status),\n    approval_status:str(r.approval_status),\n    approved_by:'',\n    approved_at:'',\n    estimated_analysis_cost_usd:Number(r.estimated_analysis_cost_usd)||0,\n    manager_note:str(r.manager_note),\n    notes:notes\n  }});\n}\nreturn out;"
      },
      "id": "wf13-raw",
      "name": "Build raw_market_records Rows",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        300
      ]
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "PASTE_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "raw_market_records",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [],
          "schema": []
        },
        "options": {}
      },
      "id": "wf13-app-raw",
      "name": "Append raw_market_records",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1340,
        300
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "jsCode": "// Build market_record_registry rows for UNIQUE records only (exactly 15 columns). No external calls.\nfunction str(v){return v==null?'':String(v).trim();}\nfunction moscowIsoNow(){var m=new Date(Date.now()+10800000);return m.toISOString().replace('Z','+03:00');}\nconst now=moscowIsoNow();\nconst recs=$('Deduplicate Items').all().map(i=>i.json);\nconst out=[];\nfor(const r of recs){\n  if(str(r.dedup_status)!=='unique')continue;\n  out.push({ json: {\n    dedup_key:str(r.dedup_key),\n    source_type:str(r.source_type),\n    platform:str(r.platform),\n    source_url:str(r.source_url),\n    post_url:str(r.post_url),\n    profile_url:str(r.profile_url),\n    author_handle:str(r.author_handle),\n    text_hash:str(r.text_hash),\n    first_seen_at:now,\n    last_seen_at:now,\n    last_route:str(r.predicted_route),\n    last_processing_status:'raw_collected',\n    last_entity_type:str(r.predicted_entity_type),\n    agent_request_id:str($('Set Connector Config').first().json.agent_request_id),\n    note:'stage_3_source_foundation_vk_public_discussion'\n  }});\n}\nreturn out;"
      },
      "id": "wf13-regrows",
      "name": "Build market_record_registry Rows",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1560,
        200
      ]
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "PASTE_SPREADSHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "market_record_registry",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [],
          "schema": []
        },
        "options": {}
      },
      "id": "wf13-app-reg",
      "name": "Append market_record_registry",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1780,
        200
      ],
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "jsCode": "// One agent_requests row (exactly 21 columns). status=completed. No external calls.\n// Audience aggregates (DEC-121, aggregate-only): active_author_count / repeat_author_count computed over\n// business-relevant items \u2014 counts only, never a member list, never outreach targets.\nfunction str(v){return v==null?'':String(v).trim();}\nfunction cut(s,n){s=str(s);return s.length>n?s.slice(0,n):s;}\nconst cfg=$('Set Connector Config').first().json;\nconst recs=$('Deduplicate Items').all().map(i=>i.json);\nconst items_received=recs.length;\nconst invalid_items=recs.filter(r=>str(r.dedup_status)==='invalid').length;\nconst structurally_valid_items=items_received-invalid_items;\nconst hard_skipped_items=recs.filter(r=>str(r.dedup_status)==='hard_skipped').length;\nconst business_relevant_items=structurally_valid_items-hard_skipped_items;\nconst over_pipeline_limit=recs.filter(r=>str(r.dedup_status)==='over_pipeline_limit').length;\nconst unique=recs.filter(r=>str(r.dedup_status)==='unique').length;\nconst duplicate=recs.filter(r=>str(r.dedup_status).indexOf('duplicate')===0).length;\nconst authorCounts={};\n// Defect F: AUDIENCE aggregates = consumer/audience authors only (record_type_hint==='question_objection').\n// Competitor (competitor_activity) & editorial (market_signal) accounts are NOT audience authors. Counted over\n// UNIQUE rows only so duplicates can't inflate repeats. Counts only \u2014 never a member list, never outreach targets.\nfor(const r of recs){ if(str(r.dedup_status)!=='unique')continue; if(str(r.record_type_hint)!=='question_objection')continue; const a=str(r.author_key); if(a)authorCounts[a]=(authorCounts[a]||0)+1; }\nconst audience_author_count=Object.keys(authorCounts).length;\nconst repeat_audience_author_count=Object.keys(authorCounts).filter(a=>authorCounts[a]>=2).length;\nconst question_items=recs.filter(r=>str(r.record_type_hint)==='question_objection'&&str(r.dedup_status)==='unique').length;\nconst fixtureMode=(cfg.fixture_mode===true||str(cfg.fixture_mode).toLowerCase()==='true');\nconst groups=Array.isArray(cfg.group_allowlist)?cfg.group_allowlist.join(', '):'';\nlet notes='WF13 foundation (DEC-121): VK PUBLIC group post/comment connector, fixture-first, no external calls, no private chats/messages, no member extraction. Canonical handoff: raw_market_records -> WF14 (Lead Scout) -> public_lead_signals (manual, no auto-handoff); WF08 optional Stage 3 path. Source: '+(fixtureMode?'fixture':'live')+'. Audience aggregates are AUDIENCE-author counts only (audience_author_count='+audience_author_count+', repeat_audience_author_count='+repeat_audience_author_count+'; consumer comment authors only, excludes competitor/editor accounts) \u2014 no member lists, no outreach. Contact policy: public contacts verbatim from text only, author profile URL only if public, default manual_review.';\nif(hard_skipped_items>0){\n  const firstHard=recs.filter(r=>str(r.dedup_status)==='hard_skipped')[0];\n  notes+=' hard_skipped_items='+hard_skipped_items+'.';\n  if(firstHard){ notes+=' first_hard_skip: '+cut(str(firstHard.post_url),80)+' ['+cut(str(firstHard.relevance_reason),120)+']'; }\n}\nreturn [{ json: {\n  agent_request_id:str(cfg.agent_request_id),\n  created_at:str(cfg.created_at),\n  requested_by:str(cfg.requested_by)||'operator',\n  request_text:'VK public group post/comment discovery (allowlist): '+groups,\n  request_type:str(cfg.request_type)||'social_source_discovery',\n  source_scope:'social_public',\n  platforms:'vk',\n  query:'allowlist: '+groups,\n  region:str(cfg.region)||'\u041c\u043e\u0441\u043a\u0432\u0430/\u041c\u041e',\n  service_focus:str(cfg.service_focus)||'credit_broker',\n  requested_limit:Number(cfg.pipeline_limit)||10,\n  status:'completed',\n  plan_summary:'WF13 VK public discussion connector ('+(fixtureMode?'fixture mode':'live mode')+') -> raw_market_records + market_record_registry for the Lead Scout engine (WF14 -> public_lead_signals). Canonical Lead Scout handoff = WF14; WF08 Touchpoint Analyzer remains an OPTIONAL Stage 3 analytical path, not the mandatory handoff. One source at a time (DEC-096
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

13 - VK Public Discussion / Lead Source Connector (Stage 3.5). Uses googleSheets, httpRequest. Event-driven trigger; 24 nodes.

Source: https://github.com/CodeVinci8/vinci-ai-pilot/blob/main/n8n/workflows/13_public_discussion_or_reviews_connector_foundation.json — original creator credit. Request a take-down →

More Marketing & Ads workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Marketing & Ads

Lead Gen -> Outreach -> Reply Digest. Uses googleSheets, httpRequest, emailSend, emailReadImap. Event-driven trigger; 36 nodes.

Google Sheets, HTTP Request, Email Send +1
Marketing & Ads

Enrich And Veryify Leads. Uses httpRequest, googleSheets, googleSheetsTrigger. Event-driven trigger; 32 nodes.

HTTP Request, Google Sheets, Google Sheets Trigger
Marketing & Ads

This workflow scrapes Google Maps business listings (e.g., carpenters in Tarragona) to extract websites and email addresses — perfect for lead generation, local business prospecting, or agency outreac

HTTP Request, Google Sheets
Marketing & Ads

Categories: Lead Generation, Web Scraping, Business Automation

HTTP Request, Google Sheets
Marketing & Ads

This template finds businesses on Google Maps → writes to Google Sheets → enriches + verifies email contact so your outreach stays clean and deliverable. It includes Sticky Notes** to explain the flow

HTTP Request, Google Sheets, @Verificaremails/N8N Nodes Verificaremails +1