Ga naar de inhoud

Hoe bouw je een dagelijkse SEO-rankingrapportage in n8n?

Handmatig rankings bijhouden is een zware, repetitieve klus: data ophalen, in een sheet plakken, vergelijken met gisteren, en dan weer van voren af aan. Deze definitie laat zien hoe n8n SEMrush, Google Sheets en Slack verbindt tot één geautomatiseerde workflow die het hele proces dagelijks volgens schema afhandelt. Wil je dit niet langer met de hand doen, begin dan hier.

Bijdrage van

SaaS Hackers
Blog

Kort antwoord: Je bouwt een dagelijks SEO-rankingrapport in n8n door de API van SEMrush te koppelen om volgens schema data over zoekwoordposities op te halen, een stap voor wijzigingsdetectie uit te voeren die verschuivingen in rankings markeert, en een opgemaakte samenvatting naar Slack te sturen. De hele workflow draait automatisch, zonder handmatige exports of gedoe met spreadsheets.

Rankings bijhouden is zo'n taak die elke ochtend 20 tot 30 minuten kost als je het handmatig doet. Data ophalen uit SEMrush, in een sheet plakken, vergelijken met gisteren, de grootste stijgers en dalers markeren, een samenvatting naar het team sturen. In deze tutorial bouw je dat hele proces in n8n, zodat het elke dag vanzelf draait, nog voordat je koffie hebt gehad.

Aan het eind heb je een werkende workflow die dagelijks zoekwoordrankings uit SEMrush ophaalt, positiewijzigingen detecteert ten opzichte van de data van de dag ervoor en een overzichtelijk rapport naar een Slack-kanaal stuurt.

Wat je nodig hebt voordat je begint

  • Een n8n-instance (zelf gehost of n8n Cloud)
  • Een SEMrush API-sleutel (beschikbaar bij elk betaald SEMrush-abonnement)
  • Een Slack-workspace met een bot-token en een kanaal voor rapportages
  • Een Google Sheet om historische rankingdata op te slaan (je geheugen tussen de runs)

Stap 1: Stel de Schedule Trigger in

Elk geautomatiseerd rapport begint met een trigger. Open in n8n een nieuwe workflow en voeg een Schedule Trigger-node toe.

Stel hem in om één keer per dag te draaien. Een goede standaard is 07:00 in je lokale tijdzone, zodat het rapport in Slack staat voordat je team aan de ochtendstand-up begint.

Instellingen:

  • Trigger interval: Days
  • Run every: 1
  • At hour: 7
  • At minute: 0

Sla de node op. Dit is de hartslag van je hele workflow.

Stap 2: Haal zoekwoordrankings op uit SEMrush

Voeg na de Schedule Trigger een HTTP Request-node toe. SEMrush biedt rankingdata aan via zijn API en de HTTP Request-node van n8n handelt de aanroep netjes af.

Configureer de HTTP Request-node:

  • Methode: GET
  • URL: https://api.semrush.com/
  • Queryparameters (voeg ze elk als apart veld toe):
    • type = domain_ranks (of phrase_organic voor data op zoekwoordniveau)
    • key = je SEMrush API-sleutel
    • domain = het domein dat je volgt
    • database = je doelland-database (bijv. us voor de VS)
    • export_columns = Ph,Po,Nq,Cp,Ur (Phrase, Position, Search Volume, CPC, URL)

Gebruik voor het volgen van posities op zoekwoordniveau type=phrase_organic en voeg een phrase parameter toe voor elk zoekwoord. Als je een lijst zoekwoorden volgt, loop je daar doorheen met een n8n Split In Batches -node (behandeld in stap 3).

Hoe het antwoord eruitziet:

SEMrush geeft een tekstantwoord terug met puntkomma's als scheidingsteken. Voeg na de HTTP Request een Code-node toe om dit om te zetten naar nette JSON:

const lines = $input.first().json.data.split('\n');
const headers = lines[0].split(';');
const rows = lines.slice(1).filter(line => line.trim() !== '');

return rows.map(row => {
  const values = row.split(';');
  const obj = {};
  headers.forEach((header, i) => {
    obj[header.trim()] = values[i]?.trim();
  });
  return { json: obj };
});

Dit geeft je één item per zoekwoord met velden als Keyword, Position, Search Volume, en URL.

Stap 3: Loop door een lijst met zoekwoorden

Als je een vaste lijst zoekwoorden volgt in plaats van alle rankings van een domein op te halen, sla die lijst dan op in een Google Sheet en lees hem aan het begin van de workflow in.

Voeg vóór de HTTP Request een Google Sheets-node toe:

  • Operation: Read Rows
  • Sheet: je sheet voor het volgen van zoekwoorden (bijv. "Keywords")
  • Range: A:A (zoekwoorden in kolom A)

Voeg daarna een Split In Batches-node toe om elk zoekwoord te doorlopen en per zoekwoord een aparte SEMrush API-aanroep te doen. Zet de batchgrootte op 1 om de data schoon te houden en problemen met rate limits te voorkomen.

Verbind: Google Sheets → Split In Batches → HTTP Request → Code (parser)

Stap 4: Lees de rankings van gisteren uit Google Sheets

Voor wijzigingsdetectie heb je een nulmeting nodig. Je Google Sheet fungeert ook als historisch archief. Voeg na het parsen van de data van vandaag nog een Google Sheets-node toe om de rankings van de vorige dag te lezen.

Geef je trackingsheet de volgende kolommen:

| Date | Keyword | Position | URL | Search Volume |

Instellingen van de Google Sheets-node:

  • Operation: Read Rows
  • Filter op datum: de datum van gisteren (gebruik een expressie zoals {{ $now.minus({days: 1}).toFormat('yyyy-MM-dd') }})

Voeg daarna een Merge -node toe om de data van vandaag te koppelen aan die van gisteren op het veld Keyword . Gebruik de modus Merge by Key met Keyword als matchingveld.

Zo krijg je één gecombineerde dataset waarin elk item zowel de huidige als de vorige positie van hetzelfde zoekwoord bevat.

Stap 5: Detecteer positiewijzigingen

Voeg na de Merge-node een Code-node toe om per zoekwoord de wijziging te berekenen en grote verschuivingen te markeren.

return $input.all().map(item => {
  const today = parseInt(item.json.Position_today) || 0;
  const yesterday = parseInt(item.json.Position_yesterday) || 0;
  const change = yesterday - today; // positive = improved, negative = dropped

  let status = 'stable';
  if (change >= 3) status = 'improved';
  if (change <= -3) status = 'dropped';

  return {
    json: {
      keyword: item.json.Keyword,
      position_today: today,
      position_yesterday: yesterday,
      change: change,
      status: status,
      url: item.json.URL_today
    }
  };
});

Je kunt de drempel (nu 3 posities) aanpassen aan hoe gevoelig je de meldingen wilt hebben. Wil je ook de bestemmingspagina zelf verbeteren: zulke rankingverschuivingen wijzen vaak op pagina's die sterkere messaging of op conversie gerichte aanpassingen nodig hebben. Daarom loont het om naast je SEO-workflow beproefde best practices en voorbeelden voor SaaS-landingspagina's te bekijken.

Stap 6: Schrijf de data van vandaag terug naar Google Sheets

Sla voordat je het rapport verstuurt de rankings van vandaag op, zodat ze morgen de nulmeting vormen.

Voeg een Google Sheets-node toe:

  • Operation: Append Row
  • Koppel de velden: Date (datum van vandaag), Keyword, Position, URL, Search Volume

Dit draait na de stap voor wijzigingsdetectie, zodat je altijd een doorlopende dagelijkse historie hebt.

Stap 7: Maak het Slack-rapport op en verstuur het

Voeg een Code-node toe om het Slack-bericht op te bouwen. In een overzichtelijk rapport staan verbeterde, gedaalde en stabiele zoekwoorden apart, zodat de lezer het in minder dan 30 seconden kan scannen.

const items = $input.all().map(i => i.json);

const improved = items.filter(i => i.status === 'improved');
const dropped = items.filter(i => i.status === 'dropped');

const formatRow = (i) => 
  `• *${i.keyword}*: ${i.position_today} (was ${i.position_yesterday}, ${i.change > 0 ? '+' : ''}${i.change})`;

const message = [
  `*Daily SEO Rank Report – ${new Date().toDateString()}*`,
  '',
  improved.length > 0 ? `*Improved (${improved.length})*\n${improved.map(formatRow).join('\n')}` : '',
  dropped.length > 0 ? `*Dropped (${dropped.length})*\n${dropped.map(formatRow).join('\n')}` : '',
  `_${items.length} keywords tracked_`
].filter(Boolean).join('\n');

return [{ json: { message } }];

Voeg daarna een Slack-node toe:

  • Resource: Message
  • Operation: Send
  • Kanaal: je rapportagekanaal (bijv. #seo-reports)
  • Tekst: {{ $json.message }}

Stap 8: Voeg een foutafhandeling toe

Elke productieworkflow heeft een vangnet nodig. Voeg een Error Trigger -node toe en verbind die met een tweede Slack-node die een bericht plaatst in een #workflow-errors -kanaal als een stap mislukt.

Zo voorkom je stille fouten, waarbij het rapport simpelweg niet aankomt en niemand het merkt tot de rankings al zijn verschoven.

Zo ziet de voltooide workflow eruit

Schedule Trigger (07:00 daily)
  → Google Sheets (read keyword list)
  → Split In Batches
  → HTTP Request (SEMrush API)
  → Code (parse response)
  → Google Sheets (read yesterday's data)
  → Merge (by keyword)
  → Code (change detection)
  → Google Sheets (append today's data)
  → Code (format Slack message)
  → Slack (send report)

Totaal aantal nodes: 10 tot 11, afhankelijk van hoe je de foutafhandeling instelt. Bouwtijd voor iemand die n8n kent: ongeveer 90 minuten bij de eerste poging.

Veelvoorkomende problemen en hoe je ze oplost

SEMrush geeft lege data terug
Controleer of de parameter database overeenkomt met de juiste regionale database voor je doelmarkt. Controleer ook of je API-sleutel genoeg units heeft. Elke zoekwoordopvraag kost API-credits.

De Merge-node vindt geen overeenkomsten
Meestal is je datumnotatie niet consistent tussen de schrijfstap en de leesstap. Leg het formaat vast op yyyy-MM-dd overal met behulp van $now.toFormat('yyyy-MM-dd').

Slack-bericht is te lang
Slack blokkeert berichten van meer dan 4.000 tekens. Volg je meer dan 50 tot 60 zoekwoorden, filter de Slack-uitvoer dan zo dat alleen zoekwoorden met een wijziging van 5 of meer posities worden getoond, en link naar de volledige Google Sheet voor het complete beeld.

Rate limiting door SEMrush
Voeg een Wait-node (ingesteld op 1 seconde) toe tussen de batches in je Split In Batches-loop. De API van SEMrush staat korte pieken toe, maar aanhoudend snelle aanvragen leveren 429-fouten op.

Zo breid je deze workflow uit

Zodra de kernworkflow betrouwbaar draait, voegen drie uitbreidingen echte waarde toe:

Wekelijkse samenvatting: Voeg een tweede Schedule Trigger toe die op maandag draait, de data van de afgelopen 7 dagen uit Google Sheets leest en naast het dagelijkse rapport een wekelijkse trendsamenvatting verstuurt.

Alleen drempelmeldingen: Dupliceer de workflow en haal de dagelijkse samenvatting eruit. Stel deze versie zo in dat de Slack-node alleen afgaat als een zoekwoord op één dag meer dan 5 posities daalt. Gebruik dit voor monitoring richting klanten, waar de verhouding tussen signaal en ruis telt.

Koppeling met Google Looker Studio: Je Google Sheet is al ingericht als een nette datatabel. Koppel hem aan Looker Studio (gratis) en bouw een live grafiek met de ranking-trend die elke ochtend automatisch wordt bijgewerkt.

Veelgestelde vragen

Wat doet een n8n-workflow voor een dagelijks SEO-rankingrapport?
Hij haalt volgens een automatisch dagelijks schema data over zoekwoordposities op uit SEMrush, vergelijkt de huidige positie van elk zoekwoord met de data van de vorige dag in Google Sheets, signaleert grote rankingwijzigingen en stuurt een opgemaakte samenvatting naar een Slack-kanaal. Na het instellen draait de workflow zonder handmatige input.

Heb ik programmeerervaring nodig om dit in n8n te bouwen?
Nee, maar je moet wel basis-JavaScript kunnen lezen en aanpassen. De Code-nodes in deze workflow gebruiken eenvoudige array-methoden. Als je de voorbeelden hierboven kunt volgen en variabelenamen kunt aanpassen, kun je deze workflow bouwen. De HTTP Request-, Google Sheets- en Slack-nodes configureer je gewoon met aanklikken en invullen.

Wat kost het om deze workflow dagelijks te draaien?
n8n Cloud begint bij ongeveer $20 per maand. De API-kosten van SEMrush hangen af van je abonnement en het aantal zoekwoorden. Elke phrase_organic -opvraag kost 10 API-units. Het dagelijks volgen van 50 zoekwoorden kost 500 units, wat ruim binnen de meeste betaalde SEMrush-abonnementen valt. Slack en Google Sheets zijn voor dit gebruik gratis.

Kan ik een andere rank tracking-API gebruiken in plaats van SEMrush?
Ja. DataForSEO en Bright Data hebben allebei REST API's die werken met de HTTP Request-node van n8n volgens hetzelfde patroon als in deze tutorial. De parseerstap in de Code-node moet je dan aanpassen aan het antwoordformaat van de API die je kiest.

Wat gebeurt er als de workflow 's nachts mislukt?
De Error Trigger-node aan het einde van de workflow vangt elke fout op en stuurt een Slack-melding naar je foutenkanaal. Zonder die node blijven fouten onopgemerkt. Voeg altijd foutafhandeling toe aan geplande workflows voordat je ze als productieklaar beschouwt.

Is deze workflow geschikt voor bureaus die voor meerdere klanten werken?
Met een paar aanpassingen wel. De eenvoudigste aanpak is om de workflow per klant te dupliceren en het domein, het keywordsheet en het Slack-kanaal aan te passen. Een geavanceerdere opzet gebruikt één workflow die een configuratiesheet met klantgegevens uitleest en dynamisch de instellingen van elke klant doorloopt. Als je op het punt komt dat je hulp van buitenaf nodig hebt om SEO-rapportage, automatisering of bredere groeisystemen op te schalen, kun je via SaaS Hackers ook een expert vinden of door geverifieerde B2B SaaS SEO-bureaus bladeren voor hulp bij de implementatie.

Bijdrage van

SaaS Hackers

Vind een B2B SaaS-expert

We hebben een gids samengesteld met B2B SaaS-experts en -bureaus die we hebben beoordeeld en ingedeeld op dienst en specialisme.

Vind een expert
Alles bekijken