Skip to content

Conversation

@Alexey-Pavlov
Copy link
Contributor

This pull request adds a new utility function for tracking recommendation selections and updates the useDownShift hook to use this new function. The main idea is that we have removing SEARCH_TERM_STORAGE_KEY in src/tracker.js in autocomplete-ui, but in this library, this part is missing. I added it here, so customers who use our autocomplete library don't face issues when we send the old search term by clicking on recommendations and adding to cart.

Also, this PR improves how recommendation clicks are tracked, making the tracking logic more modular and reusable.

Tracking improvements:

  • Added a new trackRecommendationSelect function to src/utils/tracking.ts to encapsulate recommendation click tracking logic and ensure consistent storage cleanup.
  • Updated the useDownShift hook in src/hooks/useDownShift.ts to use the new trackRecommendationSelect function instead of calling the tracker directly, improving maintainability and separation of concerns.
  • Added storageRemoveItem to remove the old SEARCH_TERM_STORAGE_KEY

@Alexey-Pavlov Alexey-Pavlov requested a review from a team September 15, 2025 17:08
Copy link
Contributor

@mocca102 mocca102 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking great!

Can we add a test case similar to this in ComponentTests.stories.tsx
expect(storageGetItem(CONSTANTS.SEARCH_TERM_STORAGE_KEY)).toBeNull();

The tests seem to be failing as well (I don't think it's related to your PR) but we need to fix it

…s for search term clearing on recommendation selection
@Alexey-Pavlov
Copy link
Contributor Author

Looking great!

Can we add a test case similar to this in ComponentTests.stories.tsx expect(storageGetItem(CONSTANTS.SEARCH_TERM_STORAGE_KEY)).toBeNull();

The tests seem to be failing as well (I don't think it's related to your PR), but we need to fix it

@mocca102 Thank you for the review! It was interesting 🧠
I added:

  • test, where I add something to the store using storageSetItem, then open zero state with recs, click on one of them, and then check that SEARCH_TERM_STORAGE_KEY is null
  • fixed few getAllByText, because actually text there looks like <p class="cio-term-in-group">in Socks &amp; Underwear</p>
  • FocusFiresTrackingEvent tests were flaky, sometimes passed, sometimes not, so I overwrote Storage.prototype.setItem, I don't like it, but this way it works stably without surprises (sometimes _constructorio_requests appears to be deleted at the moment of check), and extracted it to its own helper to reduce code duplication

@mocca102
Copy link
Contributor

mocca102 commented Oct 7, 2025

  • FocusFiresTrackingEvent tests were flaky, sometimes passed, sometimes not, so I overwrote Storage.prototype.setItem, I don't like it, but this way it works stably without surprises (sometimes _constructorio_requests appears to be deleted at the moment of check), and extracted it to its own helper to reduce code duplication

Actually, I like this approach better. This LGTM.

@Alexey-Pavlov I'll approve it but please make sure to get an approval from a CDX team member as well

Copy link
Contributor

@Mudaafi Mudaafi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, I just had one comment on the new test

await userEvent.click(firstRecommendation);
}

expect(storageGetItem(CONSTANTS.SEARCH_TERM_STORAGE_KEY)).toBeNull();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this particular test is created to ensure that search_term_storage is cleared, but should we also check if the tracking event is fired using that new utility captureTrackingRequest?

Copy link
Contributor Author

@Alexey-Pavlov Alexey-Pavlov Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, we can, without any problems
Added this check ✅

Thank you for the review!

Comment on lines -508 to +557
expect(canvas.getAllByText('in Socks').length).toEqual(1);
expect(canvas.getAllByText(/in Socks/)).toHaveLength(1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing this

Comment on lines +59 to +62
export const trackRecommendationSelect = (cioClient, recommendationData: any = {}) => {
storageRemoveItem(CONSTANTS.SEARCH_TERM_STORAGE_KEY);
cioClient?.tracker.trackRecommendationClick(recommendationData);
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good abstraction

Copilot AI review requested due to automatic review settings October 8, 2025 10:42
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds functionality to automatically remove search terms from storage when recommendation clicks are tracked, addressing a consistency issue between this library and the autocomplete-ui library. It also introduces improved tracking utilities and test patterns.

  • Added trackRecommendationSelect utility function to handle recommendation clicks with storage cleanup
  • Updated useDownShift hook to use the new tracking function instead of direct tracker calls
  • Added captureTrackingRequest utility for better test reliability and reusability

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/utils/tracking.ts Added new tracking utilities including trackRecommendationSelect and captureTrackingRequest
src/hooks/useDownShift.ts Updated to use the new trackRecommendationSelect function for better separation of concerns
src/stories/tests/HooksTests.stories.tsx Updated tests to use the new captureTrackingRequest utility and improved test assertions
src/stories/tests/ComponentTests.stories.tsx Added new test for zero-state recommendation selection and updated existing test patterns

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

}
};

export const trackRecommendationSelect = (cioClient, recommendationData: any = {}) => {
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The recommendationData parameter uses any type which reduces type safety. Consider defining a proper interface for recommendation data to improve type checking and developer experience.

Suggested change
export const trackRecommendationSelect = (cioClient, recommendationData: any = {}) => {
interface RecommendationData {
podId?: string;
numResultsViewed?: number;
url?: string;
section?: string;
items?: Array<{
itemId?: string;
itemName?: string;
variationId?: string;
}>;
// Add other properties as needed
}
export const trackRecommendationSelect = (
cioClient: Nullable<ConstructorIOClient>,
recommendationData: RecommendationData = {}
) => {

Copilot uses AI. Check for mistakes.
if (key === '_constructorio_requests') {
try {
const requests = JSON.parse(value);
if (requests.some((req: any) => req?.url?.includes(urlPattern))) {
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using any type for request objects reduces type safety. Consider defining a proper interface for request objects to improve type checking.

Copilot uses AI. Check for mistakes.
Comment on lines +69 to +71
const originalSetItem = Storage.prototype.setItem;

Storage.prototype.setItem = function setItemInterceptor(key, value) {
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modifying the global Storage.prototype could cause issues if multiple components use this function simultaneously or if the restoration fails. Consider using a more isolated approach or adding proper error handling to ensure the prototype is always restored.

Copilot uses AI. Check for mistakes.
@Alexey-Pavlov Alexey-Pavlov merged commit 81bf77f into main Oct 8, 2025
9 of 10 checks passed
@Alexey-Pavlov Alexey-Pavlov deleted the ci-4786-bulk-invalid-search-term-for-recommendation-conversions branch October 8, 2025 12:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants