Join Search Console pages to GA4
correlate_gsc_to_ga4Per page: Google Search clicks (Search Console) next to what those visits did on the site (GA4 sessions, key events, revenue).
Answers questions like "which pages bring search clicks AND convert?" or "which top-ranking pages get zero conversions?". Takes the top pages by Search Console clicks and attaches GA4 numbers for the same pages over the same dates.
What the GA4 numbers count: sessions that STARTED on the page (GA4 landingPage) and came from Google organic search (sessionSource "google" AND sessionMedium "organic"). ga4_conversions, ga4_revenue and ga4_engagement_rate belong to those same sessions, so a key event counts even if it happened on a later page of the visit. ga4_conversions is the number of GA4 key events, not of converting sessions, so it can exceed ga4_sessions. Every row carries ga4_scope saying what GA4 counted.
Why this scope: a Search Console click is a click on a Google result that lands on the page, so the GA4 side has to be landing sessions from Google. Counting every session that viewed the page (pagePath) mixes in all channels and internal navigation, and inflates GA4 far above GSC. The filter is google / organic rather than the "Organic Search" channel group because that group also includes Bing, Yandex, DuckDuckGo and others, which Search Console never counts.
Do not expect ga4_sessions to equal gsc_clicks. GA4 is usually lower: visitors who block analytics or decline consent, and visits that leave before the tag loads, are clicks with no session; visits whose referrer is lost are filed under (direct) / (none), not google / organic; several clicks within one visit are one session. GA4 can be higher where its google / organic includes Google Images or Discover visits, which Search Console's web numbers leave out. Per page, Search Console credits a click to the canonical URL while GA4 records the URL actually opened, so duplicates, redirects and language variants move numbers between rows. Search Console dates are Pacific Time, GA4 uses the property's time zone. Use the numbers to compare pages, not to expect a 1:1 match.
Page matching: joined on (host, path). The Search Console URL's host and path are compared to GA4 hostName + landingPage, with lowercase host, percent-decoding, trailing slash ignored ("/foo" and "/foo/" are the same page) and no query string (GA4 landingPage never has one). Search Console URLs that fall on the same key (http and https, "/foo" and "/foo/", query string variants) are merged into one row: clicks and impressions summed, position impression-weighted, and the merged URLs listed in gsc_urls. Hosts stay separate, so a subdomain of an sc-domain property is not credited with the main domain's numbers; one GA4 has no data for gets 0.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | lookback window, default 28. The window ends 2 days ago (Search Console lag) and is the same for both sides. | |
| limit | No | max pages to return, default 30 | |
| site_url | Yes | Search Console property (must be authorized) | |
| property_id | Yes | GA4 property id (must point at the same site) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||