Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d751d0b
updated coveo analytics to include citations attach events
SimonMilord Dec 15, 2025
20cbe2a
added analytics actions for attach citation document
SimonMilord Dec 15, 2025
c8edeb0
added redux action and modified state and slice to support attaching …
SimonMilord Dec 15, 2025
a94b567
added slice test and some improvements
SimonMilord Dec 16, 2025
3eb0bfa
applied feedback
SimonMilord Dec 16, 2025
68bd4c5
Merge branch 'main' into SFINT-6550
SimonMilord Dec 16, 2025
4b9d451
reverted changes to redux actions, no longer doing those.
SimonMilord Dec 17, 2025
f669665
Merge branch 'SFINT-6550' of https://github.com/coveo/ui-kit into SFI…
SimonMilord Dec 17, 2025
8553215
applied feedback
SimonMilord Dec 17, 2025
abbf38a
Merge branch 'main' into SFINT-6550
SimonMilord Dec 17, 2025
54169f0
lockfile update, dedupe
SimonMilord Dec 17, 2025
a4b590e
Merge branch 'SFINT-6550' of https://github.com/coveo/ui-kit into SFI…
SimonMilord Dec 17, 2025
e11572a
Merge branch 'main' into SFINT-6550
SimonMilord Dec 17, 2025
ba2dd1f
changed the param of the analytics from result to citation
SimonMilord Dec 18, 2025
ff42126
Merge branch 'SFINT-6550' of https://github.com/coveo/ui-kit into SFI…
SimonMilord Dec 18, 2025
56136ef
improved the analytic
SimonMilord Dec 18, 2025
41ce274
added new detach action for citations
SimonMilord Dec 18, 2025
bcd9613
Merge branch 'main' into SFINT-6550
SimonMilord Dec 18, 2025
f7b657e
some feedback applied
SimonMilord Dec 19, 2025
2f3a605
Merge branch 'SFINT-6550' of https://github.com/coveo/ui-kit into SFI…
SimonMilord Dec 19, 2025
a136a9e
fixed the urihash sent to analytics
SimonMilord Dec 19, 2025
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 @@ -180,6 +180,10 @@ export enum SearchPageEvents {
* Identifies the custom event that gets logged when a user clicks the Detach From Case result action.
*/
caseDetach = 'caseDetach',
/**
* Identifies the click event that gets logged when a user attaches a generated answer citation to a case.
*/
generatedAnswerCitationDocumentAttach = 'generatedAnswerCitationDocumentAttach',
/**
* Identifies the cause of a search request being retried in order to regenerate an answer stream that failed.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const attachedResultPayloadDefinition = {
source: nonEmptyString,
title: requiredNonEmptyString,
uriHash: nonEmptyString,
isCitation: new BooleanValue({required: false, default: false}),
};

const RequiredAttachedResultRecord = new RecordValue({
Expand All @@ -48,7 +49,7 @@ const RequiredAttachedResultRecord = new RecordValue({
});

export const setAttachedResults = createAction(
'insight/attachToCase/setAttachedResults',
'insight/attachedResults/setAttachedResults',
(payload: SetAttachedResultsActionCreatorPayload) =>
validatePayload(payload, {
results: new ArrayValue({
Expand All @@ -62,12 +63,12 @@ export const setAttachedResults = createAction(
);

export const attachResult = createAction(
'insight/attachToCase/attach',
'insight/attachedResults/attach',
(payload: AttachedResult) => validatePayloadAndPermanentIdOrUriHash(payload)
);

export const detachResult = createAction(
'insight/attachToCase/detach',
'insight/attachedResults/detach',
(payload: AttachedResult) => validatePayloadAndPermanentIdOrUriHash(payload)
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,25 @@ import {getConfigurationInitialState} from '../configuration/configuration-state
import {
logCaseAttach,
logCaseDetach,
logCitationDocumentAttach,
} from './attached-results-analytics-actions.js';

const mockLogCaseAttach = vi.fn();
const mockLogCaseDetach = vi.fn();
const mockLogGeneratedAnswerCitationDocumentAttach = vi.fn();
const emit = vi.fn();

vi.mock('@coveo/relay');

vi.mock('coveo.analytics');
vi.mocked(CoveoInsightClient).mockImplementation(function () {
vi.mocked(CoveoInsightClient).mockImplementation(function (
this: CoveoInsightClient
) {
this.disable = () => {};
this.logCaseAttach = mockLogCaseAttach;
this.logCaseDetach = mockLogCaseDetach;
this.logGeneratedAnswerCitationDocumentAttach =
mockLogGeneratedAnswerCitationDocumentAttach;
});

vi.mocked(createRelay).mockReturnValue({
Expand Down Expand Up @@ -166,6 +172,36 @@ describe('attached results analytics actions', () => {
);
});
});

describe('logCitationDocumentAttach', () => {
it('should call coveo.analytics.logGeneratedAnswerCitationDocumentAttach properly', async () => {
await logCitationDocumentAttach(testResult)()(
engine.dispatch,
() => engine.state,
{} as ThunkExtraArguments
);

expect(
mockLogGeneratedAnswerCitationDocumentAttach
).toHaveBeenCalledTimes(1);
expect(
mockLogGeneratedAnswerCitationDocumentAttach.mock.calls[0][0]
).toStrictEqual(expectedDocumentInfo);
expect(
mockLogGeneratedAnswerCitationDocumentAttach.mock.calls[0][1]
).toStrictEqual({
generativeQuestionAnsweringId: 'unknown',
citationId: 'example documentUriHash',
documentId: {
contentIdKey: 'permanentid',
contentIdValue: 'example contentIDValue',
},
});
expect(
mockLogGeneratedAnswerCitationDocumentAttach.mock.calls[0][2]
).toStrictEqual(expectedMetadata);
});
});
});

describe('when analyticsMode is `next`', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
import {analyticsEventCaseContext} from '../analytics/insight-analytics-utils.js';
import {SearchPageEvents} from '../analytics/search-action-cause.js';
import {getCaseContextAnalyticsMetadata} from '../case-context/case-context-state.js';
import {generativeQuestionAnsweringIdSelector} from '../generated-answer/generated-answer-selectors.js';

export const logCaseAttach = (result: Result) =>
makeInsightAnalyticsActionFactory(SearchPageEvents.caseAttach)({
Expand Down Expand Up @@ -55,3 +56,30 @@ export const logCaseDetach = (result: Result) =>
};
},
});

export const logCitationDocumentAttach = (result: Result) =>
makeInsightAnalyticsActionFactory(
SearchPageEvents.generatedAnswerCitationDocumentAttach
)({
prefix: 'insight/generatedAnswerCitationDocumentAttach',
__legacy__getBuilder: (client, state) => {
validateResultPayload(result);
const metadata = getCaseContextAnalyticsMetadata(
state.insightCaseContext
);
const citation = {
generativeQuestionAnsweringId:
generativeQuestionAnsweringIdSelector(state) || 'unknown',
citationId: result.raw.urihash || result.raw.permanentid || 'unknown',
documentId: {
contentIdKey: 'permanentid',
contentIdValue: result.raw.permanentid || result.uniqueId,
},
};
return client.logGeneratedAnswerCitationDocumentAttach(
partialDocumentInformation(result, state),
citation,
metadata
);
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('attached results slice', () => {
});
const finalState = attachedResultsReducer(state, action);
expect(finalState.results).toBe(action.payload.results);
expect(finalState.results.length).toEqual(1);
expect(finalState.results.length).toBe(1);
expect(finalState.results).toContainEqual(testAttachedResult);
});

Expand All @@ -46,15 +46,15 @@ describe('attached results slice', () => {
});
const finalState = attachedResultsReducer(state, action);
expect(finalState).toStrictEqual(action.payload);
expect(finalState.results.length).toEqual(0);
expect(finalState.results.length).toBe(0);
expect(finalState.loading).toBe(true);
});

it('#attachResult correctly adds a result in the attached state', () => {
const testAttachedResult = createMockAttachedResult();
const action = attachResult(testAttachedResult);
const finalState = attachedResultsReducer(state, action);
expect(finalState.results.length).toEqual(1);
expect(finalState.results.length).toBe(1);
expect(finalState.results).toStrictEqual([testAttachedResult]);
});

Expand All @@ -71,7 +71,7 @@ describe('attached results slice', () => {
finalState = attachedResultsReducer(finalState, action);
});

expect(finalState.results.length).toEqual(attachedResults.length);
expect(finalState.results.length).toBe(attachedResults.length);
expect(finalState.results).toStrictEqual([...attachedResults]);
});

Expand All @@ -91,7 +91,7 @@ describe('attached results slice', () => {
const action = detachResult(testDetachResult);

const finalState = attachedResultsReducer(state, action);
expect(finalState.results.length).toEqual(0);
expect(finalState.results.length).toBe(0);
});

it('#detachResult will detach an attached result', () => {
Expand All @@ -106,7 +106,7 @@ describe('attached results slice', () => {
const detachAction = detachResult(testDetachResult);
const finalState = attachedResultsReducer(intermediateState, detachAction);

expect(finalState.results.length).toEqual(0);
expect(finalState.results.length).toBe(0);
});

it('#detachResult will detach the correct result among multiple attached results', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export interface AttachedResult {
* The uriHash of the attached result.
*/
uriHash?: string;
/**
* Whether the attached result is a citation.
*/
isCitation?: boolean;
}

export interface AttachedResultsState {
Expand Down
Loading
Loading