Best way to store SERP API results into Google Sheets with n8n?

I’m planning a small n8n workflow for SERP monitoring and would like to sanity-check the structure before building it.

The workflow I have in mind is:

Schedule Trigger
→ HTTP Request
→ Code
→ Google Sheets

The idea is:

  1. Run a search query on a schedule
  2. Call a Search API with an HTTP Request node
  3. Receive structured JSON results
  4. Extract fields like position, title, URL, snippet, query, and timestamp
  5. Append each organic result as a row in Google Sheets

The target sheet columns would be:

  • checked_at
  • query
  • engine
  • position
  • title
  • url
  • snippet

My main question is about the transformation step.

If the HTTP response contains an array like organic_results, is the Code node the best place to convert each result into a separate item for Google Sheets? Or is there a more idiomatic n8n way to split the array before appending rows?

I’m also wondering whether people usually store the raw API response somewhere first, then transform it, or just append the normalized rows directly.

1 Like

welcome to the n8n community @Elowen

Your structure makes sense. For the transformation step, I would usually convert each organic_results entry into its own n8n item before sending it to Google Sheets. A Code node is perfectly fine for that, especially if you want to add fields like checked_at, query, and engine consistently. The main thing is that Google Sheets works best when each incoming n8n item represents one row.

I would only store the raw API response separately if you need auditability, debugging, or future reprocessing. For a simple SERP monitoring workflow, I’d append the normalized rows directly and maybe keep the raw response only when an error happens or when the API result format changes.

So the practical shape would be: Schedule Trigger → HTTP Request → transform organic_results into separate items → Google Sheets append rows

One extra suggestion: include a unique key such as query + checked_at + position + url, or at least check for duplicates if the workflow may be retried. This avoids appending the same SERP results twice after a failed or repeated execution.

1 Like

Hey @Elowen, welcome! Your workflow structure is solid and shows you’ve thought about this carefully.

Building on what @tamy.santos shared, I want to flag one thing: you can actually skip the Code node entirely for the split step. n8n has a native “Split Out” node (previously called “Item Lists”) that does exactly this without any coding:

  • Add a Split Out node after HTTP Request
  • Set “Field To Split Out” to organic_results
  • Each result becomes its own n8n item automatically

Your structure becomes: Schedule Trigger → HTTP Request → Split Out → Edit Fields → Google Sheets

The Edit Fields node then lets you map item.position, item.title, item.url, item.snippet etc. visually without code.

That said, a Code node is totally fine too, especially if you want to add the checked_at timestamp and query field in the same step since those come from a higher level in the response (not inside organic_results).

One more tip: for deduplication, consider using Google Sheets “Append or Update” mode instead of plain “Append”, with your URL as the matching column. This way reruns won’t create duplicate rows for the same result.