Skip to main content

Scrape any website to Google Sheets automatically with n8n

Two free n8n workflow templates that take every scheduled Lection scrape and keep a Google Sheet up to date, with no duplicate rows.

What it does

Lection runs your scrape on a schedule and POSTs the finished rows to an n8n webhook. The workflow checks a shared secret, ignores test sends and empty runs, then writes the rows to Google Sheets.

Sheets template (upsert)

Every row is matched on a unique column you pick. Existing keys are updated in place, new keys are appended.

n8n-lection-to-google-sheets.json

Change-alerts template

Keeps only rows whose key is not in the sheet yet, appends them, and posts one Slack message listing the new rows.

n8n-lection-change-alerts.json

Who it is for

Competitor prices

Scrape a competitor product or pricing page weekly. One row per product, keyed on URL or SKU, updated in place so the sheet always shows the latest price.

New leads from directories and Google Maps

Scrape a results page on a schedule. Use the alerts template so only businesses you have not seen yet are added and posted to Slack.

Listing monitoring

Watch classifieds, job boards or real estate listings. Any scrape with a stable ID, URL or slug works with either template.

Set it up in 5 steps

About ten minutes the first time.

  1. 1

    Import the template into n8n

    Download the JSON file below. In n8n choose Workflows, then Import from file. Set the Sheet ID and the unique column in the Google Sheets node, attach your Google Sheets credential, and replace the placeholder webhook path with a long random string.

  2. 2

    Activate the workflow and copy the production URL

    Create a Google Sheet whose header row matches your Lection column names exactly, including the unique column such as product_url. Activate the workflow, then copy the production webhook URL (not the test URL).

  3. 3

    Create a schedule in Lection

    In Lection, open Scheduled Scrapes and create a schedule for the page you want to track. Pick the cadence (for example weekly) and the data you want to extract.

  4. 4

    Set the destination to Webhook and paste the n8n URL

    In the schedule, open the Integrations tab, pick n8n (or Custom endpoint) as the destination, and paste the production URL.

  5. 5

    Add the secret header and run once

    To use the shared secret check, choose Custom endpoint, enter the same value in the Secret field (Lection sends it as the X-Lection-Secret header), and use the same value in the Secret matches? node. Save, then click Run now to see the first rows land in your sheet.

The secret field only appears when the destination is Custom endpoint, and the payload is identical for n8n and Custom endpoint. If you pick the n8n destination, delete the Secret matches? node (or leave the secret check out) or every call will return 401.

What Lection sends

The workflows read these fields: event, dataset.rowCount, dataset.records, and schedule.name. Headers include Content-Type: application/json and, when set, X-Lection-Secret.

{
  "event": "scheduled_scrape.completed",
  "version": 1,
  "delivered_at": "2026-10-12T14:00:03.120Z",
  "schedule": {
    "id": "7c1f0c52-0d1e-4a52-9e1a-5a2b6f1e9a10",
    "name": "Competitor prices - weekly",
    "cadence": "weekly",
    "timezone": "America/New_York",
    "target_url": "https://shop.example/collections/widgets",
    "delivery_channel": "webhook"
  },
  "run": {
    "id": "b2a4d8c0-3f77-4c0e-8d1b-0a9a2f6d7e11",
    "status": "completed",
    "rows_extracted": 3
  },
  "dataset": {
    "rowCount": 3,
    "columns": ["product_url", "name", "price"],
    "records": [
      { "product_url": "https://shop.example/p/1", "name": "Widget A", "price": "19.99" },
      { "product_url": "https://shop.example/p/2", "name": "Widget B", "price": "5.00" },
      { "product_url": "https://shop.example/p/3", "name": "Widget C", "price": null }
    ]
  },
  "download": { "url": "https://.../exports/run.csv?token=...", "expires_in_seconds": 2592000 }
}

Sample values are made up. The shape matches what Lection sends and is the payload the templates were tested with in n8n 2.42.7. The Google Sheets and Slack nodes were not exercised against live accounts in that test.

Limits and troubleshooting

  • Paid plans only. Webhook delivery needs the Standard or Professional plan. Other plans fall back to email.
  • No retries. Lection waits 12 seconds for a 2xx response and then stops. The run is still saved. Keep the workflow fast.
  • No payload signature. The only check is the plain X-Lection-Secret header. Use https and a long random secret and webhook path.
  • Headers must match. The sheet header row must equal the scraped column names exactly (case-sensitive), or cells come out empty.
  • Keys must be stable. A key that changes between runs creates duplicate rows. Rows without a key are skipped by the alerts template.
  • Nothing after a test send? Expected. Use Run now.
  • 401 Unauthorized. The secret in Lection does not match the workflow, or you selected the n8n destination, which has no secret field.
  • Failed runs also send. They use the same event name, so check run.status in the payload if you want to skip them.

Frequently asked questions

Is the template free?

Yes. Both n8n workflows are free to download and edit. Webhook delivery from Lection requires a paid plan, and the Standard plan has a 30-day free trial.

Do I need a paid n8n account?

No. The workflows use the Webhook, If, Split Out, Code, Google Sheets and Slack nodes, which work in n8n Cloud and self-hosted n8n. You need a Google Sheets credential, and a Slack credential only for the alert version.

What does the upsert template do with existing rows?

Each record is matched on the unique column you set. If the key exists, that row is updated in place; if not, a new row is appended. Pick a key that does not change between runs, such as a product URL, SKU or listing ID.

How do I get alerts only for new items?

Use the change-alerts template. It reads the keys already in your sheet, keeps only records whose key is not there yet, appends them, and posts one Slack message summarizing the new rows.

Why did Lection show a webhook failure?

Usually the workflow was not active (test URL instead of production URL), the secret did not match, or the workflow took longer than 12 seconds to answer. Lection does not retry, but the run itself is still saved.

Does the test send write rows to my sheet?

No. The templates ignore the scheduled_scrape.test event on purpose. Use Run now to send a real run.

Put your sheet on autopilot

Start free, or try the Standard plan for 30 days to schedule scrapes and send them to n8n.