Skip to content
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

fix(insights): send extra parameters only for applicable versions #5558

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ See https://www.algolia.com/doc/api-reference/widgets/configure/js/`);
});

test('insights: options passes options to middleware', () => {
const insightsClient = jest.fn();
const insightsClient = Object.assign(jest.fn(), { version: '2.4.0' });
const search = new InstantSearch({
searchClient: createSearchClient(),
indexName: 'test',
Expand Down Expand Up @@ -521,7 +521,7 @@ See https://www.algolia.com/doc/api-reference/widgets/configure/js/`);

search.sendEventToInsights({
insightsMethod: 'clickedObjectIDsAfterSearch',
payload: { eventName: 'Add to cart' },
payload: { eventName: 'Add to cart' } as any,
eventType: 'click',
widgetType: 'ais.hits',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export function _buildEventPayloadsForHits({
widgetType,
eventType,
payload: {
eventName,
eventName: eventName || 'Hit Clicked',
index,
queryID,
objectIDs: objectIDsByChunk[i],
Expand All @@ -138,7 +138,7 @@ export function _buildEventPayloadsForHits({
widgetType,
eventType,
payload: {
eventName,
eventName: eventName || 'Hit Converted',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

alternatively eventName could be required in the type when it's click or convert, but not sure if that can easily be done

Copy link
Member

Choose a reason for hiding this comment

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

We could maybe have sendEventForHits satisfy both a custom payload signature and type, hit, eventName? For now though, having those defaults works for me.

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, I prefer defaults too, as typescript types aren't enforced at runtime, meaning there will be more valid events.

index,
queryID,
objectIDs: objectIDsByChunk[i],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ describe('insights', () => {
expect(document.body).toMatchInlineSnapshot(`
<body>
<script
src="https://cdn.jsdelivr.net/npm/search-insights@2.3.0/dist/search-insights.min.js"
src="https://cdn.jsdelivr.net/npm/search-insights@2.4.0/dist/search-insights.min.js"
/>
</body>
`);
Expand Down Expand Up @@ -220,7 +220,7 @@ describe('insights', () => {
expect(document.body).toMatchInlineSnapshot(`
<body>
<script
src="https://cdn.jsdelivr.net/npm/search-insights@2.3.0/dist/search-insights.min.js"
src="https://cdn.jsdelivr.net/npm/search-insights@2.4.0/dist/search-insights.min.js"
/>
</body>
`);
Expand Down Expand Up @@ -872,7 +872,7 @@ See documentation: https://www.algolia.com/doc/guides/building-search-ui/going-f
eventType: 'click',
payload: {
hello: 'world',
},
} as any,
dhayab marked this conversation as resolved.
Show resolved Hide resolved
});
expect(analytics.viewedObjectIDs).toHaveBeenCalledTimes(0);
expect(onEvent).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -909,7 +909,7 @@ See documentation: https://www.algolia.com/doc/guides/building-search-ui/going-f
eventType: 'click',
payload: {
hello: 'world',
},
} as any,
});

expect(insightsClient).toHaveBeenLastCalledWith(
Expand Down Expand Up @@ -940,7 +940,7 @@ See documentation: https://www.algolia.com/doc/guides/building-search-ui/going-f
eventType: 'click',
payload: {
hello: 'world',
},
} as any,
});
}).toWarnDev();
expect(insightsClient).toHaveBeenCalledTimes(numberOfCalls); // still the same
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,21 @@ import {

import type {
InsightsClient,
InsightsClientMethod,
InsightsEvent as _InsightsEvent,
InsightsMethod,
InsightsMethodMap,
InternalMiddleware,
Hit,
} from '../types';
import type {
AlgoliaSearchHelper,
PlainSearchParameters,
} from 'algoliasearch-helper';

export type InsightsEvent = {
insightsMethod?: InsightsClientMethod;
payload: any;
widgetType: string;
eventType: string; // 'view' | 'click' | 'conversion', but we're not restricting.
hits?: Hit[];
attribute?: string;
};

type ProvidedInsightsClient = InsightsClient | null | undefined;

export type InsightsEvent<TMethod extends InsightsMethod = InsightsMethod> =
_InsightsEvent<TMethod>;

export type InsightsProps<
TInsightsClient extends ProvidedInsightsClient = ProvidedInsightsClient
> = {
Expand All @@ -46,8 +41,13 @@ export type InsightsProps<
$$internal?: boolean;
};

const ALGOLIA_INSIGHTS_SRC =
'https://cdn.jsdelivr.net/npm/search-insights@2.3.0/dist/search-insights.min.js';
const ALGOLIA_INSIGHTS_VERSION = '2.4.0';
const ALGOLIA_INSIGHTS_SRC = `https://cdn.jsdelivr.net/npm/search-insights@${ALGOLIA_INSIGHTS_VERSION}/dist/search-insights.min.js`;

export type InsightsClientWithGlobals = InsightsClient & {
shouldAddScript?: boolean;
version?: string;
dhayab marked this conversation as resolved.
Show resolved Hide resolved
};

export type CreateInsightsMiddleware = typeof createInsightsMiddleware;

Expand All @@ -61,8 +61,7 @@ export function createInsightsMiddleware<
$$internal = false,
} = props;

let insightsClient: InsightsClient & { shouldAddScript?: boolean } =
_insightsClient || noop;
let insightsClient: InsightsClientWithGlobals = _insightsClient || noop;

if (_insightsClient !== null && !_insightsClient) {
safelyRunOnBrowser(({ window }: { window: any }) => {
Expand All @@ -81,6 +80,7 @@ export function createInsightsMiddleware<
}
window[pointer].queue.push(args);
};
window[pointer].version = ALGOLIA_INSIGHTS_VERSION;
}

insightsClient = window[pointer];
Expand Down Expand Up @@ -227,15 +227,29 @@ export function createInsightsMiddleware<
immediate: true,
});

// @ts-ignore
const insightsClientWithLocalCredentials = (method, payload) => {
return insightsClient(method, payload, {
headers: {
'X-Algolia-Application-Id': appId,
'X-Algolia-API-Key': apiKey,
},
});
};
type InsightsClientWithLocalCredentials = <
TMethod extends InsightsMethod
>(
method: TMethod,
payload: InsightsMethodMap[TMethod][0]
) => void;

let insightsClientWithLocalCredentials =
insightsClient as InsightsClientWithLocalCredentials;

if (isModernInsightsClient(insightsClient)) {
insightsClientWithLocalCredentials = (method, payload) => {
const extraParams = {
headers: {
'X-Algolia-Application-Id': appId,
'X-Algolia-API-Key': apiKey,
},
};

// @ts-ignore we are calling this only when we know that the client actually is correct
return insightsClient(method, payload, extraParams);
};
}

instantSearchInstance.sendEventToInsights = (event: InsightsEvent) => {
if (onEvent) {
Expand Down Expand Up @@ -280,3 +294,15 @@ See documentation: https://www.algolia.com/doc/guides/building-search-ui/going-f
};
};
}

function isModernInsightsClient(client: InsightsClientWithGlobals): boolean {
const [major, minor] = (client.version || '').split('.').map(Number);

/* eslint-disable @typescript-eslint/naming-convention */
const v3 = major >= 3;
const v2_4 = major === 2 && minor >= 4;
const v1_10 = major === 1 && minor >= 10;
/* eslint-enable @typescript-eslint/naming-convention */

return v3 || v2_4 || v1_10;
}
29 changes: 28 additions & 1 deletion packages/instantsearch.js/src/types/insights.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Hit } from './results';
import type {
InsightsMethodMap,
InsightsMethodMap as _InsightsMethodMap,
InsightsClient as _InsightsClient,
} from 'search-insights';

Expand All @@ -11,8 +12,34 @@ export type {
OnUserTokenChange as InsightsOnUserTokenChange,
} from 'search-insights';

export type InsightsMethodMap = _InsightsMethodMap;
export type InsightsClientMethod = keyof InsightsMethodMap;

/**
* Method allowed by the insights middleware.
*/
export type InsightsMethod =
| 'clickedObjectIDsAfterSearch'
| 'clickedObjectIDs'
| 'clickedFilters'
| 'convertedObjectIDsAfterSearch'
| 'convertedObjectIDs'
| 'convertedFilters'
| 'viewedObjectIDs'
| 'viewedFilters';

/**
* The event sent to the insights middleware.
*/
export type InsightsEvent<TMethod extends InsightsMethod = InsightsMethod> = {
insightsMethod?: TMethod;
payload: InsightsMethodMap[TMethod][0];
widgetType: string;
eventType: string; // 'view' | 'click' | 'conversion', but we're not restricting.
hits?: Hit[];
attribute?: string;
};

export type InsightsClientPayload = {
eventName: string;
queryID: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('insights', () => {
<body>
<div />
<script
src="https://cdn.jsdelivr.net/npm/search-insights@2.3.0/dist/search-insights.min.js"
src="https://cdn.jsdelivr.net/npm/search-insights@2.4.0/dist/search-insights.min.js"
/>
</body>
`);
Expand Down
14 changes: 7 additions & 7 deletions tests/common/widgets/hits/insights.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function createInsightsTests(setup: HitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -133,7 +133,7 @@ export function createInsightsTests(setup: HitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 25;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -264,7 +264,7 @@ export function createInsightsTests(setup: HitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -344,7 +344,7 @@ export function createInsightsTests(setup: HitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -428,7 +428,7 @@ export function createInsightsTests(setup: HitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -522,7 +522,7 @@ export function createInsightsTests(setup: HitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -602,7 +602,7 @@ export function createInsightsTests(setup: HitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down
14 changes: 7 additions & 7 deletions tests/common/widgets/infinite-hits/insights.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function createInsightsTests(setup: InfiniteHitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -133,7 +133,7 @@ export function createInsightsTests(setup: InfiniteHitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 25;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -264,7 +264,7 @@ export function createInsightsTests(setup: InfiniteHitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -344,7 +344,7 @@ export function createInsightsTests(setup: InfiniteHitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -428,7 +428,7 @@ export function createInsightsTests(setup: InfiniteHitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -522,7 +522,7 @@ export function createInsightsTests(setup: InfiniteHitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down Expand Up @@ -602,7 +602,7 @@ export function createInsightsTests(setup: InfiniteHitsSetup, act: Act) {
const delay = 100;
const margin = 10;
const hitsPerPage = 2;
window.aa = jest.fn();
window.aa = Object.assign(jest.fn(), { version: '2.4.0' });
const options = {
instantSearchOptions: {
indexName: 'indexName',
Expand Down
Loading