@affiliateo/web 4.9.0 → 4.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -233,7 +233,8 @@ signs in next (or nobody) isn't counted as the person who just left. Their Live
233
233
  Chat goes too: the next person to open the chat starts a new thread.
234
234
  Everything already recorded stays with them. Tracking carries on as before:
235
235
  same visitor id, same affiliate. If a different user signs in without a
236
- sign-out in between, the browser switches to them on its own.
236
+ sign-out in between, the browser switches to them on its own, and the last
237
+ person's Live Chat thread is forgotten first.
237
238
 
238
239
  ## Live Chat
239
240
 
@@ -254,7 +255,7 @@ import { openChat } from '@affiliateo/web'
254
255
  // Never load the chat
255
256
  <AffiliateoProvider appId="..." chat={false}>
256
257
 
257
- // Your own look, over the dashboard's (4.15.0); leave out what the dashboard should decide
258
+ // Your own look, over the dashboard's (4.9.0); leave out what the dashboard should decide
258
259
  <AffiliateoProvider appId="..." chatLook={{ color: '#7C3AED', iconColor: '#FFFFFF', sendColor: '#007AFF', placeholder: 'Ask us anything', style: 'glass', corner: 'bottom-left', size: 56 }}>
259
260
  ```
260
261
 
@@ -269,6 +270,16 @@ the script tag, `data-chat-color`, `data-chat-icon-color`, `data-chat-send-color
269
270
 
270
271
  ## Changelog
271
272
 
273
+ - **4.9.1:** a different user signing in with `identify()` (no `logout()` in
274
+ between) now forgets the last person's Live Chat thread first, as a sign-out
275
+ does, and the bubble learns the new user without a reload. Signing in from
276
+ anonymous keeps the person's own thread. With it, from the bubble itself
277
+ (chat.js, served by Affiliateo, so every site gets it with no update): its
278
+ screen-reader labels in the visitor's language, the visitor's chat key no
279
+ longer in the live connection's address (a one-minute ticket instead), only
280
+ the page's address without its query or fragment sent to the inbox, and a
281
+ size set in code kept within 40 to 80.
282
+
272
283
  - **4.9.0:** Live Chat (see above): the chat bubble loads by itself once the
273
284
  business switches it on; new `chat` prop and `openChat()`, `closeChat()`,
274
285
  `showChatBubble()`, `hideChatBubble()`. `logout()` and `reset()` forget the
package/dist/chat.d.ts CHANGED
@@ -18,6 +18,12 @@ export interface LoadLiveChatOptions {
18
18
  visitorId: string | null;
19
19
  /** The signed-in user id from identify(). Null while opted out. */
20
20
  userId: string | null;
21
+ /**
22
+ * Read again just before chat.js is added (4.9.1): a sign-in or a switch
23
+ * of person while the config check is on its way must not load the bubble
24
+ * with the last person's id. Falls back to `userId`.
25
+ */
26
+ getUserId?: () => string | null;
21
27
  /** 'hidden' loads the chat without a bubble, for a site that opens it from its own button. */
22
28
  bubble?: 'visible' | 'hidden';
23
29
  theme?: 'light' | 'dark';
@@ -34,6 +40,13 @@ export declare function closeChat(): void;
34
40
  export declare function showChatBubble(): void;
35
41
  /** Hide the chat bubble, and close the window. */
36
42
  export declare function hideChatBubble(): void;
43
+ /**
44
+ * Who is signed in now (identify(), 4.9.1). chat.js reads the user once, when
45
+ * it loads: a sign-in after that reaches it through __setUser, which also
46
+ * forgets a DIFFERENT person's thread (signing in from anonymous keeps it).
47
+ * Still loading: it reads data-user when it runs, so that is updated.
48
+ */
49
+ export declare function setLiveChatUser(userId: string): void;
37
50
  /**
38
51
  * The person signed out (logout(), reset()): their chat goes, so whoever
39
52
  * signs in next starts a new thread. The token chat.js keeps goes from
package/dist/chat.js CHANGED
@@ -54,8 +54,9 @@ export function loadLiveChat(opts) {
54
54
  script.setAttribute('data-app', opts.appId);
55
55
  if (opts.visitorId)
56
56
  script.setAttribute('data-visitor', opts.visitorId);
57
- if (opts.userId)
58
- script.setAttribute('data-user', opts.userId.slice(0, 128));
57
+ const userId = opts.getUserId ? opts.getUserId() : opts.userId;
58
+ if (userId)
59
+ script.setAttribute('data-user', userId.slice(0, 128));
59
60
  if (opts.bubble === 'hidden')
60
61
  script.setAttribute('data-bubble', 'hidden');
61
62
  if (opts.theme)
@@ -96,6 +97,22 @@ export function showChatBubble() {
96
97
  export function hideChatBubble() {
97
98
  chatGlobal()?.hide?.();
98
99
  }
100
+ /**
101
+ * Who is signed in now (identify(), 4.9.1). chat.js reads the user once, when
102
+ * it loads: a sign-in after that reaches it through __setUser, which also
103
+ * forgets a DIFFERENT person's thread (signing in from anonymous keeps it).
104
+ * Still loading: it reads data-user when it runs, so that is updated.
105
+ */
106
+ export function setLiveChatUser(userId) {
107
+ if (typeof window === 'undefined' || typeof document === 'undefined')
108
+ return;
109
+ const chat = chatGlobal();
110
+ if (chat?.__setUser) {
111
+ chat.__setUser(userId);
112
+ return;
113
+ }
114
+ document.querySelector('script[data-affiliateo-chat]')?.setAttribute('data-user', userId.slice(0, 128));
115
+ }
99
116
  /**
100
117
  * The person signed out (logout(), reset()): their chat goes, so whoever
101
118
  * signs in next starts a new thread. The token chat.js keeps goes from
package/dist/provider.js CHANGED
@@ -6,7 +6,7 @@ import { isLikelyBot } from './bot-detect';
6
6
  import { isDevHost } from './dev-host';
7
7
  import { mintTurnstileToken, consumeTurnstileToken } from './turnstile';
8
8
  import { usableUserId } from './user-id';
9
- import { forgetLiveChat, loadLiveChat } from './chat';
9
+ import { forgetLiveChat, loadLiveChat, setLiveChatUser } from './chat';
10
10
  const DEFAULT_API_URL = 'https://affiliateo.com';
11
11
  const LS_VISITOR_ID = 'affiliateo_visitor_id';
12
12
  const LS_REF = 'affiliateo_ref';
@@ -336,7 +336,15 @@ export function AffiliateoProvider({ appId, campaignId, apiUrl, allowedHostnames
336
336
  log('identify skipped: not a user id (empty, over 128 characters, or a placeholder like "null", "guest" or "0")', { user_id: userId });
337
337
  return;
338
338
  }
339
+ // A DIFFERENT person signing in on this browser (4.9.1): the last
340
+ // person's Live Chat thread was theirs, so it goes first, as on a
341
+ // sign-out. Signing in from anonymous keeps it (the same person who
342
+ // was writing). chat.js is told who is signed in now either way.
343
+ const previous = usableUserId(lsGet(LS_USER_ID));
344
+ if (previous && previous !== uid)
345
+ forgetLiveChat(appIdRef.current);
339
346
  lsSet(LS_USER_ID, uid);
347
+ setLiveChatUser(uid);
340
348
  const cid = appIdRef.current;
341
349
  const vid = visitorIdRef.current;
342
350
  const queue = queueRef.current;
@@ -1042,6 +1050,8 @@ export function AffiliateoProvider({ appId, campaignId, apiUrl, allowedHostnames
1042
1050
  appId: resolvedAppId,
1043
1051
  visitorId: optedOut ? null : visitorIdRef.current ?? lsGet(LS_VISITOR_ID),
1044
1052
  userId: optedOut ? null : usableUserId(lsGet(LS_USER_ID)),
1053
+ // Read again when the bubble is added: a sign-in meanwhile counts.
1054
+ getUserId: () => (isOptedOut() ? null : usableUserId(lsGet(LS_USER_ID))),
1045
1055
  bubble: chat === 'hidden' ? 'hidden' : 'visible',
1046
1056
  look: chatLook,
1047
1057
  log,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@affiliateo/web",
3
- "version": "4.9.0",
3
+ "version": "4.9.1",
4
4
  "description": "Affiliateo web SDK: affiliate attribution and tracking for web apps",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",