diff --git a/lib/__tests__/init.test.ts b/lib/__tests__/init.test.ts index 21acf6e3..b2599ae3 100644 --- a/lib/__tests__/init.test.ts +++ b/lib/__tests__/init.test.ts @@ -1,6 +1,7 @@ import { getCookie, MONTH } from "../_tokenUtils"; import AlgoliaAnalytics from "../insights"; import * as utils from "../utils"; +import { createUUID } from "../utils/uuid"; jest.mock("../utils", () => ({ __esModule: true, @@ -240,6 +241,23 @@ describe("init", () => { setUserToken.mockRestore(); }); + it("should save anonymous userToken as cookie when useCookie is set to true later", () => { + analyticsInstance.init({ + apiKey: "***", + appId: "XXX" + }); + + analyticsInstance.setUserToken(`anonymous-${createUUID()}`); + + analyticsInstance.init({ + partial: true, + useCookie: true + }); + + expect(document.cookie).toEqual( + expect.stringMatching(/^_ALGOLIA=anonymous-/) + ); + }); it("should replace existing options when called again", () => { analyticsInstance.init({ apiKey: "apiKey1", diff --git a/lib/_tokenUtils.ts b/lib/_tokenUtils.ts index eb122620..e9c83508 100644 --- a/lib/_tokenUtils.ts +++ b/lib/_tokenUtils.ts @@ -31,6 +31,24 @@ export const getCookie = (name: string): string => { return ""; }; +export function checkIfAnonymousToken(token: number | string): boolean { + if (typeof token === "number") { + return false; + } + + return token.indexOf("anonymous-") === 0; +} + +export function saveTokenAsCookie(this: AlgoliaAnalytics): void { + const foundToken = getCookie(COOKIE_KEY); + if ( + this._userToken && + (!foundToken || foundToken === "" || foundToken.indexOf("anonymous-") !== 0) + ) { + setCookie(COOKIE_KEY, this._userToken, this._cookieDuration); + } +} + export function setAnonymousUserToken( this: AlgoliaAnalytics, inMemory = false diff --git a/lib/init.ts b/lib/init.ts index 40d52c17..8a1a6004 100644 --- a/lib/init.ts +++ b/lib/init.ts @@ -1,5 +1,5 @@ import { DEFAULT_ALGOLIA_AGENTS } from "./_algoliaAgent"; -import { MONTH } from "./_tokenUtils"; +import { checkIfAnonymousToken, MONTH } from "./_tokenUtils"; import type AlgoliaAnalytics from "./insights"; import { isUndefined, isNumber } from "./utils"; @@ -80,6 +80,8 @@ You can visit https://algolia.com/events/debugger instead.`); this.setUserToken(options.userToken); } else if (!this._userToken && !this._userHasOptedOut && this._useCookie) { this.setAnonymousUserToken(); + } else if (checkIfTokenNeedsToBeSaved(this)) { + this.saveTokenAsCookie(); } } @@ -110,3 +112,15 @@ function setOptions( ) ); } + +function checkIfTokenNeedsToBeSaved(target: AlgoliaAnalytics): boolean { + if (target._userToken === undefined) { + return false; + } + + return ( + checkIfAnonymousToken(target._userToken) && + target._useCookie && + !target._userHasOptedOut + ); +} diff --git a/lib/insights.ts b/lib/insights.ts index 4ce33c0a..86ed2f0c 100644 --- a/lib/insights.ts +++ b/lib/insights.ts @@ -11,7 +11,8 @@ import { MONTH, setAuthenticatedUserToken, onAuthenticatedUserTokenChange, - getAuthenticatedUserToken + getAuthenticatedUserToken, + saveTokenAsCookie } from "./_tokenUtils"; import { clickedObjectIDsAfterSearch, @@ -78,6 +79,7 @@ class AlgoliaAnalytics { getVersion: typeof getVersion; addAlgoliaAgent: typeof addAlgoliaAgent; + saveTokenAsCookie: typeof saveTokenAsCookie; setUserToken: typeof setUserToken; setAnonymousUserToken: typeof setAnonymousUserToken; getUserToken: typeof getUserToken; @@ -110,6 +112,7 @@ class AlgoliaAnalytics { this.addAlgoliaAgent = addAlgoliaAgent.bind(this); + this.saveTokenAsCookie = saveTokenAsCookie.bind(this); this.setUserToken = setUserToken.bind(this); this.setAnonymousUserToken = setAnonymousUserToken.bind(this); this.getUserToken = getUserToken.bind(this);