{
  "name": "Track competitor G2 reviews in Google Sheets",
  "nodes": [
    {
      "id": "b7e2d914-0001-4c01-9001-000000000001",
      "name": "Every Monday morning",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        0,
        460
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "b7e2d914-0002-4c02-9002-000000000002",
      "name": "Set the products to watch",
      "type": "n8n-nodes-base.set",
      "position": [
        260,
        460
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b7e2d914-0010-4c10-9010-+1234567890",
              "name": "productUrls",
              "type": "array",
              "value": "[\"https://www.g2.com/products/asana/reviews\", \"https://www.g2.com/products/trello/reviews\"]"
            },
            {
              "id": "b7e2d914-0011-4c11-9011-+1234567890",
              "name": "maxReviewsPerProduct",
              "type": "number",
              "value": "25"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "b7e2d914-0003-4c03-9003-000000000003",
      "name": "Fetch reviews for each product",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        520,
        460
      ],
      "parameters": {
        "memory": 128,
        "actorId": "johnvc~g2-reviews-api",
        "resource": "Actors",
        "operation": "Run actor and get dataset",
        "customBody": "={{ JSON.stringify({ productUrls: $json.productUrls, maxReviewsPerProduct: $json.maxReviewsPerProduct }) }}"
      },
      "typeVersion": 1
    },
    {
      "id": "b7e2d914-0004-4c04-9004-000000000004",
      "name": "Keep rows that are real reviews",
      "type": "n8n-nodes-base.filter",
      "position": [
        780,
        460
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b7e2d914-0041-4c41-9041-+1234567890",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.result_type }}",
              "rightValue": "review"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b7e2d914-0005-4c05-9005-000000000005",
      "name": "Shape review rows for the sheet",
      "type": "n8n-nodes-base.code",
      "position": [
        1040,
        460
      ],
      "parameters": {
        "jsCode": "// One row per G2 review, trimmed to what fits a spreadsheet.\n// The pros and cons fields are where the buying objections live, so they\n// stay whole; the long free-text answer is truncated instead.\nconst weekOf = $now.toFormat('yyyy-MM-dd');\n\nconst clip = (s, n) => {\n  const v = String(s || '').replace(/\\s+/g, ' ').trim();\n  return v.length > n ? v.slice(0, n - 3) + '...' : v;\n};\n\nreturn $input.all().map((item) => {\n  const r = item.json;\n  // G2 does not expose a star rating on every review, so this is often blank.\n  const rating = typeof r.rating === 'number' ? r.rating : '';\n  return {\n    json: {\n      'Week of': weekOf,\n      Product: r.productName || '',\n      Rating: rating,\n      Title: clip(r.title, 200),\n      Pros: clip(r.pros, 700),\n      Cons: clip(r.cons, 700),\n      'Reviewer role': r.reviewerRole || '',\n      'Company size': r.companySize || '',\n      'Date published': String(r.datePublished || '').slice(0, 10),\n      'Review link': r.reviewUrl || '',\n      'Review ID': r.reviewId || '',\n    },\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "b7e2d914-0006-4c06-9006-000000000006",
      "name": "Append this week's reviews",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1300,
        460
      ],
      "parameters": {
        "columns": {
          "value": {},
          "mappingMode": "autoMapInputData",
          "matchingColumns": []
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b7e2d914-0090-4c90-9090-000000000090",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -620,
        40
      ],
      "parameters": {
        "width": 520,
        "height": 1140,
        "content": "## Track competitor G2 reviews in Google Sheets\n\nNo ScrapingBee account, no Bright Data account, and no AI model. Every week this workflow pulls the latest G2 reviews for the products you list and appends one row each to your sheet: product, the pros and cons in the reviewer's own words, their role, company size, star rating where G2 published one, and a link back to the review.\n\nPoint it at your own product and your two closest competitors. The Cons column then becomes a running list of the objections a prospect will bring to your next sales call, written by people who already switched.\n\n**Who's it for**\nProduct marketers tracking competitive positioning, founders watching what churned users say next, and sales teams who want battlecards built from evidence rather than guesswork.\n\n**How it works**\n1. A schedule trigger fires once a week\n2. One Set node holds the G2 product URLs you want to watch\n3. The Apify node pulls the reviews for each product\n4. A Code node trims the long text fields so the sheet stays readable\n\n**Setup**\n1. Create a free Apify account and add your API token to the Apify credential\n2. Connect your Google account in the Sheets node and pick a spreadsheet\n3. Paste the G2 review URLs you care about into the config node, for example g2.com/products/asana/reviews\n\n**Good to know**\nAbout four tenths of a cent per review, so three products at 25 reviews each is roughly 30 cents a week.\nG2 does not attach a star rating to every review. In testing about 40 percent carried one, so treat a blank Rating as unrated rather than as zero. The pros and cons text is there on every row.\nReviews are appended every run, so use the Review ID column to drop duplicates when you chart it.\nActor: https://apify.com/johnvc/g2-reviews-api?fpr=9n7kx3&fp_sid=n8n"
      },
      "typeVersion": 1
    },
    {
      "id": "b7e2d914-0091-4c91-9091-000000000091",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -40,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 1. Schedule\nRuns every Monday morning. Change the cadence, or swap in a manual trigger while you test."
      },
      "typeVersion": 1
    },
    {
      "id": "b7e2d914-0092-4c92-9092-000000000092",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        220,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 2. Your input\nThe G2 product URLs to watch and how many reviews to pull for each. This is the only node you edit."
      },
      "typeVersion": 1
    },
    {
      "id": "b7e2d914-0093-4c93-9093-000000000093",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        480,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 3. Fetch\nPulls the reviews for each product. Add your Apify credential here."
      },
      "typeVersion": 1
    },
    {
      "id": "b7e2d914-0094-4c94-9094-000000000094",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        740,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 4. Clean\nDrops any product that returned an error, so only real reviews reach the sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "b7e2d914-0095-4c95-9095-000000000095",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1000,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 5. Shape\nTrims the long text fields so a row fits a spreadsheet cell."
      },
      "typeVersion": 1
    },
    {
      "id": "b7e2d914-0096-4c96-9096-000000000096",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1260,
        60
      ],
      "parameters": {
        "color": 7,
        "width": 240,
        "height": 240,
        "content": "### 6. Deliver\nPick your spreadsheet and tab. Columns map automatically."
      },
      "typeVersion": 1
    },
    {
      "id": "b7e2d914-0080-4c80-9080-000000000080",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        220,
        760
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 240,
        "content": "### Watch your rivals, not just yourself\nThe point of a G2 monitor is the products you do NOT own. Put your own product first in the list and your two closest competitors after it, then read the Cons column as your objection list."
      },
      "typeVersion": 1
    },
    {
      "id": "b7e2d914-0081-4c81-9081-000000000081",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        660,
        760
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 240,
        "content": "### Self-hosting n8n?\nThere is also a dedicated community node for this actor: `n8n-nodes-g2-reviews-api` on npm."
      },
      "typeVersion": 1
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "connections": {
    "Every Monday morning": {
      "main": [
        [
          {
            "node": "Set the products to watch",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set the products to watch": {
      "main": [
        [
          {
            "node": "Fetch reviews for each product",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch reviews for each product": {
      "main": [
        [
          {
            "node": "Keep rows that are real reviews",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keep rows that are real reviews": {
      "main": [
        [
          {
            "node": "Shape review rows for the sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Shape review rows for the sheet": {
      "main": [
        [
          {
            "node": "Append this week's reviews",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}