fix: keep the ads wait window tied to the search loading state - #779
Conversation
|
Hi! I'm VTEX IO CI/CD Bot and I'll be helping you to publish your app! 🤖 Please select which version do you want to release:
And then you just need to merge your PR when you are ready! There is no need to create a release commit/tag.
|
|
Beep boop 🤖 I noticed you didn't make any changes at the
In order to keep track, I'll create an issue if you decide now is not a good time
|
e35b99c to
e812ed0
Compare
e812ed0 to
e3e5b0b
Compare
The wait for sponsored products was armed from the ads loading state alone, so a refired ads request (term, selected facets or identity change) sent an already rendered PLP back to the loading state, making the page flicker. The wait is now armed only while the organic search is loading, and released when the ads request settles or after ADS_MAX_WAIT_MS. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
e3e5b0b to
50efcf9
Compare
|
Your PR has been merged! App is being published. 🚀 After the publishing process has been completed (check #vtex-io-releases) and doing A/B tests with the new version, you can deploy your release by running:
After that your app will be updated on all accounts. For more information on the deployment process check the docs. 📖 |
What problem is this solving?
Since v3.143.0 the PLP flickers: the result loads partially, the loader shows up again and only then the page renders. Reported on a store with no active campaigns (so ads always come back empty), where rolling back to v3.141.2 makes it go away (reported by
telhanorte, but noticed in other stores such asdrogal).The wait for sponsored products introduced in v3.143.0 was armed from the ads loading state alone:
Nothing tied it to the organic search state, and
isAdsLoadinggoes back totrueafter the first paint, becauseuseAdsrefires its request wheneverterm,selectedFacetsor the ads identity change (@vtex/ads-reactdeps). On this storeselectedFacetschanges whenfacetsFromSessionresolves asynchronously (SearchQuery.js:352). So: search resolves → gallery renders → ads become pending again →loading: true+products: []→ loader is back → ads return empty → gallery renders again.The intended behavior, per Ads Frictionless Integration on Store Framework, is kept: the organic result does wait for ads (bounded by a timeout) so sponsored and organic products land in the same paint.
What changed
useMergeResultsnow arms the wait only while the organic search is itself loading, so waiting can extend a loader that is already on screen but can never turn a rendered result back into one. It is released on the first of:ADS_MAX_WAIT_MS(2s).Ads pending while the search has already resolved keeps the loader — that is the intended wait. Ads pending after the result is rendered does nothing, structurally.
Also guarded
searchQuery.databefore rewritingdata.productSearch:dataisundefinedwhile Apollo is loading, which is exactly the state the wait now holds on purpose.How to test it?
Search for
coral(or any term) on this workspace without active campaigns - Workspace: the loader must appear once and stay until the ads request settles, then render the result. No second loader, no flicker.Also worth checking: facet navigation, pagination (the wait is first-page only), and a store with active sponsored campaigns, such as eletroangeloni in the new ads workspace (keeps working and showing ads for term
sanduicheira).yarn test: 16 suites, 96 tests passing.react/__tests__/useMergeResults.test.jscovers both directions — the wait happens, the 2s cap releases, ads becoming pending after the render never brings the loader back, and a new search re-arms the wait.Describe alternatives you've considered, if any.
Dropping the wait altogether (pure merge hook) removes the flicker but reintroduces the layout shift of sponsored products popping into a rendered gallery — rejected, since waiting is the behavior the RFC asks for.
Related to / Depends on
Fixes the regression introduced in v3.143.0 (
refactor: timeout to wait ads before rendering). Affects every version in the 3.143.x line.One trade-off worth reviewing: stores with no campaigns still wait for the (empty) ads response.
ADS_MAX_WAIT_MSbounds only the artificial hold this hook applies — it never cancels, truncates or short-circuits the search request. When the limit expires with the search still loading, the hold is dropped andsearchQuery.loadinggoes back to being whatever Apollo reports, so the loader stays until the search actually responds. The limit is also counted from the moment the search starts, not from when it resolves: a search that takes 1.5s leaves ads only 500ms of wait. The RFC covers this trade-off — simultaneous requests, low ads response time, and a timeout so ads don't delay the final result — but note that the 2s here is a UI-side ceiling, not a timeout on the ads request itself. A request-level timeout would have to come from@vtex/ads-react/ads-core, which does not expose one today.How does this PR make you feel? 🔗