@meetelise/chat 1.58.1 → 1.59.0

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/src/MyPubnub.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { getTrackingParams } from "./trackingParams";
1
2
  import { AxiosError } from "axios";
2
3
  import Pubnub, { ListenerParameters, MessageEvent } from "pubnub";
3
4
 
@@ -792,6 +793,7 @@ class MyPubnub {
792
793
  buildingSlug: this.buildingSlug,
793
794
  userId: this.buildingWebchatView?.userId, // this userid is actually the AI user!
794
795
  leadSource: this.leadSource,
796
+ trackingParams: getTrackingParams(this.orgSlug),
795
797
  widgetType: this.widgetType,
796
798
  isDevState: shouldCreateAsDevState(location.href),
797
799
  // Read by the backend only for orgs in the org-level webchat rollout.
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import { getTrackingParams } from "../../trackingParams";
2
3
  import { html, LitElement, PropertyValueMap, TemplateResult } from "lit";
3
4
  import { customElement, property, query, state } from "lit/decorators.js";
4
5
  import "../actions/international-phone-input";
@@ -872,6 +873,7 @@ export class TourScheduler extends LitElement {
872
873
  email_address: this.email,
873
874
  phone_number: phoneNumber,
874
875
  building_id: this.buildingId,
876
+ tracking_params: getTrackingParams(this.orgSlug),
875
877
  first_name: this.firstNameInput?.value ?? this.firstNameInputValue,
876
878
  last_name: this.lastNameInput?.value ?? this.lastNameInputValue,
877
879
  tour_type: tourTypeForSubmission[this.tourType],
@@ -1,3 +1,4 @@
1
+ import { getTrackingParams } from "../../trackingParams";
1
2
  import axios from "axios";
2
3
  import { css, html, LitElement, TemplateResult } from "lit";
3
4
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -512,6 +513,7 @@ const createTextWithUs = async (
512
513
  // @ts-ignore
513
514
  query_params: Object.fromEntries(queryParams.entries()),
514
515
  conversation_tracking_id: chatId,
516
+ tracking_params: getTrackingParams(orgSlug),
515
517
  lead_sources_with_timestamps: (leadSourcesWithTimestamps ?? []).map(
516
518
  (source) => snakify({ ...source })
517
519
  ),
@@ -1,3 +1,4 @@
1
+ import { getTrackingParams } from "../../trackingParams";
1
2
  import { css, html, LitElement, TemplateResult } from "lit";
2
3
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3
4
  import { customElement, property, query, state } from "lit/decorators.js";
@@ -865,6 +866,7 @@ const createEmail = async (
865
866
  // @ts-ignore
866
867
  query_params: Object.fromEntries(queryParams.entries()),
867
868
  conversation_tracking_id: chatId,
869
+ tracking_params: getTrackingParams(orgSlug),
868
870
  lead_sources_with_timestamps: (leadSourcesWithTimestamps ?? []).map(
869
871
  (source) => snakify({ ...source })
870
872
  ),
@@ -1,3 +1,4 @@
1
+ import { getTrackingParams } from "../trackingParams";
1
2
  import { css, html, LitElement, TemplateResult } from "lit";
2
3
  import { customElement, property, state } from "lit/decorators.js";
3
4
  import { classMap } from "lit/directives/class-map.js";
@@ -1519,6 +1520,7 @@ const overrideContactUsForm = async (
1519
1520
  first_message: formValues.message,
1520
1521
  building_id: buildingWebchatView.id,
1521
1522
  is_external_form: true,
1523
+ tracking_params: getTrackingParams(orgSlug),
1522
1524
  lead_sources: [
1523
1525
  ...new Set(
1524
1526
  leadSource
@@ -0,0 +1,32 @@
1
+ import { expect } from "@esm-bundle/chai";
2
+ import { getTrackingParams } from "./trackingParams";
3
+
4
+ const originalUrl = window.location.href;
5
+
6
+ afterEach(() => {
7
+ localStorage.removeItem("xdtid");
8
+ window.history.replaceState(null, "", originalUrl);
9
+ });
10
+
11
+ it("reads Greystar's xdtid from localStorage", () => {
12
+ localStorage.setItem("xdtid", "from-storage");
13
+ window.history.replaceState(null, "", "?xdtid=from-url");
14
+
15
+ expect(getTrackingParams("greystar")).to.deep.equal({
16
+ xdtid: "from-storage",
17
+ });
18
+ });
19
+
20
+ it("falls back to the xdtid URL param", () => {
21
+ window.history.replaceState(null, "", "?xdtid=from-url");
22
+
23
+ expect(getTrackingParams("greystar")).to.deep.equal({ xdtid: "from-url" });
24
+ });
25
+
26
+ it("returns null when nothing is found or the org has no config", () => {
27
+ expect(getTrackingParams("greystar")).to.equal(null);
28
+
29
+ localStorage.setItem("xdtid", "from-storage");
30
+ expect(getTrackingParams("avb")).to.equal(null);
31
+ expect(getTrackingParams(null)).to.equal(null);
32
+ });
@@ -0,0 +1,42 @@
1
+ interface TrackingParamSource {
2
+ key: string;
3
+ localStorageKey?: string;
4
+ queryParam?: string;
5
+ }
6
+
7
+ // Client-specific values sent with each new lead and passed to the client's PMS. Add a client here.
8
+ const TRACKING_PARAMS_BY_ORG_SLUG: Record<string, TrackingParamSource[]> = {
9
+ // Greystar's cross-domain tracking id, set by their GTM; localStorage outlives the landing URL.
10
+ greystar: [{ key: "xdtid", localStorageKey: "xdtid", queryParam: "xdtid" }],
11
+ };
12
+
13
+ const readLocalStorage = (key: string): string | null => {
14
+ try {
15
+ return localStorage.getItem(key);
16
+ } catch (_) {
17
+ return null;
18
+ }
19
+ };
20
+
21
+ const readQueryParam = (key: string): string | null => {
22
+ try {
23
+ return new URLSearchParams(window.location.search).get(key);
24
+ } catch (_) {
25
+ return null;
26
+ }
27
+ };
28
+
29
+ export const getTrackingParams = (
30
+ orgSlug: string | null | undefined
31
+ ): Record<string, string> | null => {
32
+ const sources = orgSlug ? TRACKING_PARAMS_BY_ORG_SLUG[orgSlug] : undefined;
33
+ if (!sources) return null;
34
+ const params: Record<string, string> = {};
35
+ for (const source of sources) {
36
+ const value =
37
+ (source.localStorageKey && readLocalStorage(source.localStorageKey)) ||
38
+ (source.queryParam && readQueryParam(source.queryParam));
39
+ if (value) params[source.key] = value;
40
+ }
41
+ return Object.keys(params).length ? params : null;
42
+ };