Skip to content

Conversation

Fondryext
Copy link
Contributor

This PR upgrades our analytics calls to the next major version, also called the Events API. As part of this work, analytics calls have changed shape, and some deprecated properties have been dropped.
J=WAT-4651
TEST=auto,manual

Updated auto tests. Ran test site locally and saw events all the way to snowflake.

Fondryext and others added 2 commits April 7, 2025 12:53
This PR upgrades our analytics calls to the next major
version, also called the Events API. As part of this
work, analytics calls have changed shape, and some deprecated
properties have been dropped.
J=WAT-4651
TEST=auto,manual

Updated auto tests. Ran test site locally and saw events all the
way to snowflake.
Copy link
Contributor

github-actions bot commented Apr 7, 2025

Current unit coverage is 91.4992993928071%
Current visual coverage is 77.20391807658059%
Current combined coverage is 92.01680672268908%

@@ -1,5 +1,5 @@
import React, { PropsWithChildren } from 'react';
import { provideAnalytics, AnalyticsConfig } from '@yext/analytics';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This AnalyticsConfig has changed shape in the new analytics, the old one was actually very search specific and had properties like experienceKey - the new one is very high level and only requires an auth type and an auth key. I think because of this alone this is breaking.

Choose a reason for hiding this comment

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

Yeh I think this makes sense to me.

queryId,
verticalKey: verticalKey || '',
url,
fieldName,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we drop 'searcher' and 'fieldName'

verticalKey: verticalKey,
newPage,
currentPage,
totalPageCount
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We drop all three of these page-related values.

Choose a reason for hiding this comment

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

Hm so we're just no longer sending that data with the event after this change? Or is that information picked up elsewhere?

Choose a reason for hiding this comment

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

If this was never actually being used, then that's fine. Otherwise I'd want to keep sending (and recording) that information. Just wanted to double check.

currentPage: number,
totalPageCount: number
) => void {
export function usePaginationAnalytics(): () => void {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function changes signature

analytics?.report({
type: 'AUTO_COMPLETE_SELECTION',
...(queryId && { queryId }),
suggestedSearchText
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We drop suggestedSearchText

Copy link
Contributor

Choose a reason for hiding this comment

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

That's interesting, seems like it'd be a pretty relevant piece of data for this

Copy link
Contributor Author

@Fondryext Fondryext Apr 10, 2025

Choose a reason for hiding this comment

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

How do you mean? Interesting that analytics dropped it from their new system, or that I followed it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting that analytics dropped it. We should ofc follow whatever their system supports / expects

@coveralls
Copy link

coveralls commented Apr 7, 2025

Coverage Status

coverage: 86.688% (-0.5%) from 87.142%
when pulling 6ae8d8e on dev/events-api
into 055c51d on main.

@@ -90,10 +93,19 @@ export function SectionHeader(props: SectionHeaderProps): JSX.Element {
console.error('Unable to report a vertical view all event. Missing field: queryId.');
return;
}
if (!experienceKey) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need a check for locale or searchId? Or are those automatically set

Copy link
Contributor Author

Choose a reason for hiding this comment

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

locale can be unset in the event payload so passing it possible undefined is ok. For searchId we could also add error handling if the searchId is not present.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hm as I think about it, our analytics are all based off query id now right? Probably not necessary to require the search id if we don't see that changing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually trying to send an analytics event without search id crashes out, as I recall. My understanding was that the events are based on the first search id of a query, which is the same as the query id.

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it, so it seems necessary, but also that it should be automatically set elsewhere correct? Therefore not requiring any extra check here?

Copy link
Contributor Author

@Fondryext Fondryext Apr 14, 2025

Choose a reason for hiding this comment

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

I agree a check would be nice, and I will add it. Could you elaborate the second comment? What should be set, the searchId? Isn't that pulled from the meta state? I'm not sure we have any guarantees about that.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry maybe I was misunderstanding your prior comment. The way I read it was that the search id was being set as the query id by default somewhere up the chain in the SDK somewhere. Feel free to disregard. I agree adding a check is good then

Choose a reason for hiding this comment

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

Hm, locale really isn't required? I agree about adding a check for the search id if it's required.

analytics?.report({
type: 'AUTO_COMPLETE_SELECTION',
...(queryId && { queryId }),
suggestedSearchText
Copy link
Contributor

Choose a reason for hiding this comment

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

That's interesting, seems like it'd be a pretty relevant piece of data for this

package.json Outdated
@@ -1,6 +1,6 @@
{
"name": "@yext/search-ui-react",
"version": "1.8.2",
"version": "1.8.3",
Copy link
Contributor

Choose a reason for hiding this comment

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

My debounce change is 1.8.3 so this will have to change - I assume to 2.0.0 since this has breaking changes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this change is a draft.

@@ -90,10 +93,19 @@ export function SectionHeader(props: SectionHeaderProps): JSX.Element {
console.error('Unable to report a vertical view all event. Missing field: queryId.');
return;
}
if (!experienceKey) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Got it, so it seems necessary, but also that it should be automatically set elsewhere correct? Therefore not requiring any extra check here?


/**
* Returns a service that can be used to report analytics events.
*
* @public
*/
export function useAnalytics(): AnalyticsService | null {
export function useAnalytics(): AnalyticsEventService | null {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

So if we want to hide all analytics stuff, we'd need to make our own service implementation, which has the report() method which calls the analytics report() behind the scenes. This would involve making our own event payload interface, perhaps with fewer properties than the analytics one, and maybe with no search object, instead having all properties on the top level

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this would be a good idea given that we want to abstract away the analytics code like you said

@Fondryext Fondryext marked this pull request as ready for review June 24, 2025 13:45
@Fondryext Fondryext requested a review from a team as a code owner June 24, 2025 13:45
searchTerm?: string;
}

//todo - how many of these do we want to delete?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I want to prune these down - open to what we use as our canonical list.

Choose a reason for hiding this comment

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

Is there a reason we want to prune these down? At the very least, I imagine we want things like map pin, auto complete selection, the paginates, chat impression, search clear, etc.

Choose a reason for hiding this comment

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

So as we discussed, let's pare this down based on user event types and then consider any remaining enum types more individually. If it's clearly search related or has been used before, include it. If it's clearly for another product, exclude it, etc. Use your discretion, but feel free to loop in Baigel / others if you want a 2nd opinion while I'm out.

@@ -9,5 +9,9 @@ Analytics event types for cta click, title click, and citation click.
**Signature:**

```typescript
<<<<<<< HEAD

Choose a reason for hiding this comment

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

Don't we need to resolve this?

@@ -130,7 +130,7 @@ export type CardAnalyticsType = CardCtaEventType | FeedbackType;
export type CardComponent<T = DefaultRawDataType> = (props: CardProps<T>) => JSX.Element;

// @public
export type CardCtaEventType = 'CTA_CLICK' | 'TITLE_CLICK' | 'CITATION_CLICK' | 'DRIVING_DIRECTIONS' | 'VIEW_WEBSITE' | 'TAP_TO_CALL';
export type CardCtaEventType = 'CTA_CLICK' | 'TITLE' | 'CITATION_CLICK' | 'DRIVING_DIRECTIONS' | 'WEBSITE' | 'TAP_TO_CALL';

Choose a reason for hiding this comment

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

Any reason this changed?

Choose a reason for hiding this comment

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

We decided to change these back so that future folks won't need to update their code from "TITLE_CLICK" to "title", etc. We'd just map our enum to the analytics one internally.

@@ -939,8 +947,10 @@ export interface UnknownFieldTypeDisplayProps {
// @public
export function updateLocationIfNeeded(searchActions: SearchActions, intents: SearchIntent[], geolocationOptions?: PositionOptions): Promise<void>;

// Warning: (ae-forgotten-export) The symbol "SearchAnalyticsEventService" needs to be exported by the entry point index.d.ts

Choose a reason for hiding this comment

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

What is this warning about? Do we need to actually export the service like it suggests?

action: feedbackType,
entity: entityId,
locale,
searchId,

Choose a reason for hiding this comment

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

Hm is the different indenting between this line and the line before intentional

verticalKey: verticalKey,
newPage,
currentPage,
totalPageCount

Choose a reason for hiding this comment

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

Hm so we're just no longer sending that data with the event after this change? Or is that information picked up elsewhere?

searchTerm?: string;
}

//todo - how many of these do we want to delete?

Choose a reason for hiding this comment

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

Is there a reason we want to prune these down? At the very least, I imagine we want things like map pin, auto complete selection, the paginates, chat impression, search clear, etc.

Copy link

@vijay267 vijay267 left a comment

Choose a reason for hiding this comment

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

Generally looks good! Had some comments about specific details, but I like the wrapper, and overall the changes make sense.

verticalKey: verticalKey,
newPage,
currentPage,
totalPageCount

Choose a reason for hiding this comment

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

If this was never actually being used, then that's fine. Otherwise I'd want to keep sending (and recording) that information. Just wanted to double check.

@@ -130,7 +130,7 @@ export type CardAnalyticsType = CardCtaEventType | FeedbackType;
export type CardComponent<T = DefaultRawDataType> = (props: CardProps<T>) => JSX.Element;

// @public
export type CardCtaEventType = 'CTA_CLICK' | 'TITLE_CLICK' | 'CITATION_CLICK' | 'DRIVING_DIRECTIONS' | 'VIEW_WEBSITE' | 'TAP_TO_CALL';
export type CardCtaEventType = 'CTA_CLICK' | 'TITLE' | 'CITATION_CLICK' | 'DRIVING_DIRECTIONS' | 'WEBSITE' | 'TAP_TO_CALL';

Choose a reason for hiding this comment

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

We decided to change these back so that future folks won't need to update their code from "TITLE_CLICK" to "title", etc. We'd just map our enum to the analytics one internally.

searchTerm?: string;
}

//todo - how many of these do we want to delete?

Choose a reason for hiding this comment

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

So as we discussed, let's pare this down based on user event types and then consider any remaining enum types more individually. If it's clearly search related or has been used before, include it. If it's clearly for another product, exclude it, etc. Use your discretion, but feel free to loop in Baigel / others if you want a 2nd opinion while I'm out.

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