-
Notifications
You must be signed in to change notification settings - Fork 5
fix: added search tracking changes #699
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
79372fd
766db58
5a8779c
644e2c7
bd73bee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,6 +49,14 @@ export function isPdpPage() { | |
| return !!document.querySelector('meta[name="sku"]'); | ||
| } | ||
|
|
||
| /** | ||
| * Search-result page detection via .search-results container. | ||
| * @returns {boolean} | ||
| */ | ||
| function isSearchPage() { | ||
| return !!document.querySelector('.search-results'); | ||
| } | ||
|
|
||
| /** | ||
| * Product display name for Adobe Analytics productID (Magento parity: ;{name};;;;). | ||
| * @returns {string} | ||
|
|
@@ -335,12 +343,102 @@ export function trackProdView(attempt = 0) { | |
| } | ||
|
|
||
| /** | ||
| * Initialize Adobe Analytics instrumentation (prodView on PDP). | ||
| * Derive onsiteSearchToolType from the current URL ?type= param. | ||
| * Matches AEM logic: recipe → browseRecipe, article → browseArticle, else siteSearch. | ||
| * @returns {string} | ||
| */ | ||
| function getSearchToolTypeFromUrl() { | ||
| const params = new URLSearchParams(window.location.search); | ||
| const type = (params.get('type') || '').toLowerCase(); | ||
| if (type === 'recipe') return 'browseRecipe'; | ||
| if (type === 'article') return 'browseArticle'; | ||
| return 'siteSearch'; | ||
| } | ||
|
|
||
| /** | ||
| * Set digitalData search properties and fire the matching Launch direct-call rule. | ||
| * Mirrors AEM setDigitalDataForSearch(). Called after every search run in the | ||
| * search-results widget so onsiteSearchTerm/Results/ToolType are always populated. | ||
| * @param {string} searchTerm - The search string entered by the user | ||
| * @param {string} toolType - 'siteSearch' | 'browseRecipe' | 'browseArticle' | ||
| * @param {number} resultCount - Total number of results returned | ||
| */ | ||
| export function setDigitalDataForSearch(searchTerm, toolType, resultCount) { | ||
| window.digitalData = window.digitalData || {}; | ||
| window.digitalData.page = window.digitalData.page || {}; | ||
| window.digitalData.page.pageInfo = window.digitalData.page.pageInfo || {}; | ||
|
|
||
| if (resultCount === 0) { | ||
| const satellite = getSatellite(); | ||
| if (satellite?.track) { | ||
| satellite.track('nullSearch'); | ||
| debugLog('Adobe Analytics nullSearch fired', { searchTerm, toolType }); | ||
| } | ||
| } else { | ||
| window.digitalData.page.pageInfo.onsiteSearchTerm = searchTerm || ''; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you confirm the lauch has a data element changed rule watching these |
||
| window.digitalData.page.pageInfo.onsiteSearchToolType = toolType; | ||
| window.digitalData.page.pageInfo.onsiteSearchResults = resultCount; | ||
| debugLog('Adobe Analytics search data set', window.digitalData.page.pageInfo); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Attach a MutationObserver to #results-count so digitalData is updated | ||
| * automatically every time the search widget finishes a runSearch cycle. | ||
| * @param {Element} resultsCountEl | ||
| */ | ||
| function attachSearchResultsObserver(resultsCountEl) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This observer fires on every Is that what you want @awasthiruchi?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @dylandepass confirmed with the legacy AEM code and live site's Network tab that setDigitalDataForSearch() only fires after genuine search results come back, not on pagination/filter changes.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated code to fire only on new search term. |
||
| let lastSearchTerm = null; | ||
| const observer = new MutationObserver(() => { | ||
| const params = new URLSearchParams(window.location.search); | ||
| const searchTerm = params.get('search') || ''; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This runs for every live-search prefix, so typing one zero-result term can fire nullSearch several times. Debounce the tracking path and emit once for the final settled query. |
||
| // Only fire on an actual new search term, not pagination/filter changes | ||
| if (searchTerm === lastSearchTerm) return; | ||
| lastSearchTerm = searchTerm; | ||
| const toolType = getSearchToolTypeFromUrl(); | ||
| const count = parseInt(resultsCountEl.textContent, 10) || 0; | ||
| setDigitalDataForSearch(searchTerm, toolType, count); | ||
| }); | ||
| observer.observe(resultsCountEl, { childList: true, characterData: true }); | ||
| } | ||
|
|
||
| /** | ||
| * Initialize search analytics tracking on search-result pages. | ||
| * Observes #results-count — written by the search widget after every runSearch — | ||
| * so no changes to the widget itself are needed. | ||
| * Falls back to a MutationObserver on the container if the widget hasn't rendered yet. | ||
| */ | ||
| export function trackSearchResults() { | ||
| const container = document.querySelector('.search-results'); | ||
| if (!container) return; | ||
|
|
||
| const resultsCountEl = container.querySelector('#results-count'); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MutationObserver does not replay the count update that happened before attachment, so the initial URL-driven search is missed. I confirmed this by loading: The page rendered 163 results, but |
||
| if (resultsCountEl) { | ||
| attachSearchResultsObserver(resultsCountEl); | ||
| return; | ||
| } | ||
|
|
||
| // #results-count is injected dynamically by buildSearchFiltering — wait for it | ||
| const containerObserver = new MutationObserver((_, obs) => { | ||
| const el = container.querySelector('#results-count'); | ||
| if (el) { | ||
| obs.disconnect(); | ||
| attachSearchResultsObserver(el); | ||
| } | ||
| }); | ||
| containerObserver.observe(container, { childList: true, subtree: true }); | ||
| } | ||
|
|
||
| /** | ||
| * Initialize Adobe Analytics instrumentation (prodView on PDP, search tracking on search pages). | ||
| * @returns {void} | ||
| */ | ||
| export function initInstrumentation() { | ||
| debugLog('Adobe Analytics instrumentation loaded'); | ||
| if (isPdpPage()) { | ||
| trackProdView(); | ||
| } | ||
| if (isSearchPage()) { | ||
| trackSearchResults(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set the search fields on
digitalData.page.pageInfobefore calling satellite.track('nullSearch') otherwise the rule sees missing or stale term and result values.