diff --git a/examples/index.html b/examples/index.html index cbb4c4c..a58bd9b 100644 --- a/examples/index.html +++ b/examples/index.html @@ -19,6 +19,7 @@

Gist for Web

Embed Banner Embed Floating Message Embed HTML Floating Message + Set Anonymous Custom Attribute Log In Log Out @@ -32,7 +33,7 @@

Gist for Web

Dev Setup Options { siteId: "siteid", dataCenter: "us", env: "dev", logging: true } */ - Gist.setup({ siteId: "a5ec106751ef4b34a0b9", dataCenter: "eu", logging: true, env: "prod" }); + Gist.setup({ siteId: "a5ec106751ef4b34a0b9", dataCenter: "eu", logging: true, env: "prod", useAnonymousSession: true }); Gist.setUserToken("ABC123"); Gist.setCurrentRoute("home"); @@ -116,6 +117,10 @@

Gist for Web

} }, "x-gist-floating-bottom-right"); } + + function addAnonymousCustomAttribute() { + Gist.setCustomAttribute("cio_anonymous_id", "123456"); + } \ No newline at end of file diff --git a/src/gist.js b/src/gist.js index fa86f72..e38dc45 100644 --- a/src/gist.js +++ b/src/gist.js @@ -4,6 +4,7 @@ import { startQueueListener, checkMessageQueue, stopSSEListener } from "./manage import { setUserToken, clearUserToken, useGuestSession } from "./managers/user-manager"; import { showMessage, embedMessage, hideMessage, removePersistentMessage, fetchMessageByInstanceId, logBroadcastDismissedLocally } from "./managers/message-manager"; import { setUserLocale } from "./managers/locale-manager"; +import { setCustomAttribute, clearCustomAttributes, removeCustomAttribute } from "./managers/custom-attribute-manager"; import { setupPreview } from "./utilities/preview-mode"; export default class { @@ -58,6 +59,18 @@ export default class { setUserLocale(userLocale); } + static setCustomAttribute(key, value) { + return setCustomAttribute(key, value); + } + + static clearCustomAttributes() { + clearCustomAttributes(); + } + + static removeCustomAttribute(key) { + return removeCustomAttribute(key); + } + static async clearUserToken() { if (this.config.isPreviewSession) return; clearUserToken(); diff --git a/src/managers/custom-attribute-manager.js b/src/managers/custom-attribute-manager.js new file mode 100644 index 0000000..698b6b3 --- /dev/null +++ b/src/managers/custom-attribute-manager.js @@ -0,0 +1,82 @@ +import { log } from '../utilities/log'; +import { setKeyToLocalStore, getKeyFromLocalStore, clearKeyFromLocalStore } from '../utilities/local-storage'; + +const customAttributesLocalStoreName = "gist.web.customAttributes"; +const defaultExpiryInDays = 30; + +// Internal map to store custom attributes in memory +let customAttributesMap = new Map(); + +function loadCustomAttributesFromStorage() { + const storedAttributes = getKeyFromLocalStore(customAttributesLocalStoreName); + if (storedAttributes) { + try { + customAttributesMap = new Map(storedAttributes); + } catch { + customAttributesMap = new Map(); + } + } else { + customAttributesMap = new Map(); + } +} + +function saveCustomAttributesToStorage() { + const attributesArray = Array.from(customAttributesMap.entries()); + const expiryDate = new Date(); + expiryDate.setDate(expiryDate.getDate() + defaultExpiryInDays); + + setKeyToLocalStore(customAttributesLocalStoreName, attributesArray, expiryDate); + log(`Saved ${customAttributesMap.size} custom attributes to storage with TTL of ${defaultExpiryInDays} days`); +} + +loadCustomAttributesFromStorage(); + +export function setCustomAttribute(key, value) { + if (!key || typeof key !== 'string') { + log(`Invalid key for custom attribute: ${key}`); + return false; + } + + customAttributesMap.set(key, value); + saveCustomAttributesToStorage(); + log(`Set custom attribute "${key}" to "${value}"`); + return true; +} + +export function getCustomAttribute(key) { + if (!key || typeof key !== 'string') { + log(`Invalid key for custom attribute: ${key}`); + return null; + } + + return customAttributesMap.get(key) || null; +} + +export function getAllCustomAttributes() { + return new Map(customAttributesMap); +} + +export function clearCustomAttributes() { + customAttributesMap.clear(); + clearKeyFromLocalStore(customAttributesLocalStoreName); + log(`Cleared all custom attributes`); +} + +export function removeCustomAttribute(key) { + if (!key || typeof key !== 'string') { + log(`Invalid key for custom attribute: ${key}`); + return false; + } + + const existed = customAttributesMap.has(key); + customAttributesMap.delete(key); + + if (customAttributesMap.size > 0) { + saveCustomAttributesToStorage(); + } else { + clearKeyFromLocalStore(customAttributesLocalStoreName); + } + + log(`Removed custom attribute "${key}"`); + return existed; +} diff --git a/src/managers/message-manager.js b/src/managers/message-manager.js index 6b6180b..d9d2d34 100644 --- a/src/managers/message-manager.js +++ b/src/managers/message-manager.js @@ -18,6 +18,7 @@ import { } from "./message-component-manager"; import { resolveMessageProperties } from "./gist-properties-manager"; import { positions, addPageElement } from "./page-component-manager"; +import { getAllCustomAttributes } from "./custom-attribute-manager"; import { checkMessageQueue } from "./queue-manager"; import { isMessageBroadcast, markBroadcastAsSeen, markBroadcastAsDismissed } from './message-broadcast-manager'; import { markUserQueueMessageAsSeen } from './message-user-queue-manager'; @@ -126,7 +127,8 @@ function loadMessageComponent(message, elementId = null) { messageId: message.messageId, instanceId: message.instanceId, livePreview: false, - properties: message.properties + properties: message.properties, + customAttributes: Object.fromEntries(getAllCustomAttributes()) } var url = `${settings.GIST_VIEW_ENDPOINT[Gist.config.env]}/index.html` window.addEventListener('message', handleGistEvents);