Track Internal Search
Internal site search reveals what users are looking for that they could not find through navigation. It is one of the highest-signal events you can track: search queries show intent, zero-results searches show content gaps, and repeated searches show friction.
How most sites handle search results
Section titled “How most sites handle search results”Before implementing, identify how your search results page works:
- URL parameter — most common:
/search?q=term,/results?query=pricing,/search?s=term - dataLayer push from the search results template — best when you control the CMS
- Hash-based or SPA routing —
/search#termor dynamic route
Option A — URL parameter reading (no code required)
Section titled “Option A — URL parameter reading (no code required)”If your search results appear at a URL like /search?q=your+query, GTM can read the query from the URL using a built-in URL variable.
-
Create a URL Variable for the Search Query
In GTM → Variables → New:
- Variable type: URL
- Component type: Query
- Query key:
q(replace with your site’s actual search parameter — check the URL in your browser) - Name:
URL - Search Query
-
Create a Page View Trigger for Search Results
- Trigger type: Page View
- Fire on: Some Page Views
- Condition:
Page Pathcontains/search(adjust to match your search URL pattern) - Add a second condition:
{{URL - Search Query}}does not equal “ (empty string)
-
Create a GA4 Event Tag
- Tag type: Google Analytics: GA4 Event
- Event name:
search - Parameters:
search_term→{{URL - Search Query}}page_path→{{Page Path}}
- Trigger: the Page View trigger above
-
Test in Preview Mode
Perform a search on your site. Verify the URL contains your parameter, then check the Summary pane for the
searchevent with the correctsearch_termvalue.
GA4 - search
- Type
- Google Analytics: GA4 Event
- Trigger
- Page View - search results page
- Variables
-
URL - Search QueryPage Path
Option B — dataLayer push (recommended for full control)
Section titled “Option B — dataLayer push (recommended for full control)”Push from your search results template for zero-results tracking and result count metadata.
Push this on your search results page after results are loaded.
// Add this to your search results page templatewindow.dataLayer = window.dataLayer || [];window.dataLayer.push({ event: 'search', search_term: 'your-term-from-server', // Replace with server-side template variable search_results_count: 42, // Replace with actual count from server search_has_results: true, // false if 0 results search_category: 'all' // if your search has category filtering});In a Next.js or similar SSR application:
// In your search results page componentuseEffect(() => { window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'search', search_term: router.query.q, search_results_count: results.total, search_has_results: results.total > 0 });}, [results]);-
Add the dataLayer push to your search results template. Push after results are loaded, not on page load.
-
Create a Custom Event Trigger
- Trigger type: Custom Event
- Event name:
search
-
Create Data Layer Variables
DLV - search_term→search_termDLV - search_results_count→search_results_countDLV - search_has_results→search_has_results
-
Create a GA4 Event Tag
- Event name:
search - Parameters:
search_term→{{DLV - search_term}}search_results_count→{{DLV - search_results_count}}search_has_results→{{DLV - search_has_results}}
- Trigger: the Custom Event trigger
- Event name:
-
Test in Preview Mode
Perform searches with and without results. Each should fire a
searchevent with the correctsearch_termandsearch_results_count.
Tracking zero-results searches
Section titled “Tracking zero-results searches”Zero-results searches are content gaps. Create a separate GA4 conversion event or audience for them:
In GA4 → Admin → Events → Mark as Key Event: create a filtered event for searches where search_has_results = false.
Or use a Custom Audience in GA4: users who triggered search with parameter search_has_results = false.
Export these queries to a spreadsheet weekly and review them with your content team.
Test it
Section titled “Test it”- Open GTM Preview and perform a search on your site
- Check the Summary pane for the
searchevent - Verify
search_termmatches what you searched - If using the dataLayer approach, verify
search_results_countis correct - Perform a search that returns no results and verify
search_has_resultsisfalse - Check GA4 DebugView for the
searchevent with parameters
Common gotchas
Section titled “Common gotchas”URL parameter is different per search integration. WordPress uses s=, Algolia uses query=, Elasticsearch uses various parameters. Check your search URL before configuring the URL variable.
Search query contains PII. If users search for their own email addresses or account numbers, those values flow into GA4. Consider scrubbing PII patterns from search_term before pushing. See the PII Detection recipe.
Autocomplete results never load a search page. If your search uses live autocomplete without a results page navigation, the Page View trigger will not fire. Use a custom event from your autocomplete component’s onSelect handler.