@meetelise/chat 1.51.15 → 1.52.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/dist/src/WebComponent/launcher/Launcher.d.ts +3 -1
- package/dist/src/WebComponent/me-chat.d.ts +1 -0
- package/dist/src/googleReserve.d.ts +17 -0
- package/package.json +1 -1
- package/public/dist/index.js +182 -181
- package/src/WebComponent/Scheduler/tour-scheduler.ts +4 -0
- package/src/WebComponent/launcher/Launcher.ts +13 -1
- package/src/WebComponent/me-chat.ts +19 -6
- package/src/googleReserve.test.ts +60 -0
- package/src/googleReserve.ts +48 -0
|
@@ -63,6 +63,7 @@ import { getTimezoneAbbreviation } from "../../getTimezoneString";
|
|
|
63
63
|
import startOfDay from "date-fns/startOfDay";
|
|
64
64
|
import isSameDay from "date-fns/isSameDay";
|
|
65
65
|
import { LeadSourceMultitouchClient } from "../LeadSourceMultitouchClient";
|
|
66
|
+
import { readGoogleReserveReferral } from "../../googleReserve";
|
|
66
67
|
import fetchBuildingUnitsSummary, {
|
|
67
68
|
UnitSummary,
|
|
68
69
|
} from "../../fetchBuildingUnitsSummary";
|
|
@@ -742,6 +743,7 @@ export class TourScheduler extends LitElement {
|
|
|
742
743
|
unit: selectedUnit,
|
|
743
744
|
conversationTrackingId: this.leadSourceClient?.chatId ?? null,
|
|
744
745
|
});
|
|
746
|
+
const googleReferral = readGoogleReserveReferral();
|
|
745
747
|
const data = {
|
|
746
748
|
referrer: document.referrer,
|
|
747
749
|
email_address: this.email,
|
|
@@ -774,6 +776,8 @@ export class TourScheduler extends LitElement {
|
|
|
774
776
|
}
|
|
775
777
|
) ?? []
|
|
776
778
|
).map((source) => snakify({ ...source })),
|
|
779
|
+
google_rwg_token: googleReferral?.rwgToken,
|
|
780
|
+
google_referral_building_id: googleReferral?.buildingId,
|
|
777
781
|
};
|
|
778
782
|
|
|
779
783
|
const url = `https://app.meetelise.com/platformApi/state/create/v2/scheduleMe`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { html, LitElement, TemplateResult, css } from "lit";
|
|
1
|
+
import { html, LitElement, PropertyValues, TemplateResult, css } from "lit";
|
|
2
2
|
import { customElement, property, state } from "lit/decorators.js";
|
|
3
3
|
import { createRef, ref, Ref } from "lit/directives/ref.js";
|
|
4
4
|
import { launcherStyles } from "./launcherStyles";
|
|
@@ -65,6 +65,9 @@ export class Launcher extends LitElement {
|
|
|
65
65
|
@property({ type: Boolean })
|
|
66
66
|
isFirstMount = false;
|
|
67
67
|
|
|
68
|
+
@property({ attribute: false })
|
|
69
|
+
openSSTWindowOnLoad = false;
|
|
70
|
+
|
|
68
71
|
@property({ attribute: false })
|
|
69
72
|
autoOpenChatWidget = false;
|
|
70
73
|
|
|
@@ -283,6 +286,15 @@ export class Launcher extends LitElement {
|
|
|
283
286
|
tourSchedulerRef: Ref<TourScheduler> = createRef();
|
|
284
287
|
calculatorWindowRef: Ref<FeeCalculator> = createRef();
|
|
285
288
|
|
|
289
|
+
willUpdate(changedProperties: PropertyValues<this>): void {
|
|
290
|
+
if (
|
|
291
|
+
changedProperties.has("openSSTWindowOnLoad") &&
|
|
292
|
+
this.openSSTWindowOnLoad
|
|
293
|
+
) {
|
|
294
|
+
this.isSSTWindowOpen = true;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
286
298
|
updated = async (): Promise<void> => {
|
|
287
299
|
this.attachOnClickToEmailUsWindow();
|
|
288
300
|
this.attachOnClickToSSTWindow();
|
|
@@ -71,6 +71,10 @@ import {
|
|
|
71
71
|
|
|
72
72
|
import "./chat-additional-actions";
|
|
73
73
|
import { LeadSourceMultitouchClient } from "./LeadSourceMultitouchClient";
|
|
74
|
+
import {
|
|
75
|
+
shouldOpenTourSchedulerFromUrl,
|
|
76
|
+
storeGoogleReserveReferral,
|
|
77
|
+
} from "../googleReserve";
|
|
74
78
|
|
|
75
79
|
@customElement("me-chat")
|
|
76
80
|
export class MEChat extends LitElement {
|
|
@@ -187,6 +191,9 @@ export class MEChat extends LitElement {
|
|
|
187
191
|
@state()
|
|
188
192
|
private showTourNextToChat = false;
|
|
189
193
|
|
|
194
|
+
@state()
|
|
195
|
+
private openTourSchedulerOnLoad = false;
|
|
196
|
+
|
|
190
197
|
@state()
|
|
191
198
|
private displayPubnubChat = false;
|
|
192
199
|
|
|
@@ -321,19 +328,24 @@ export class MEChat extends LitElement {
|
|
|
321
328
|
|
|
322
329
|
this.attachOnClickToLauncher();
|
|
323
330
|
|
|
324
|
-
|
|
331
|
+
storeGoogleReserveReferral(this.buildingWebchatView?.id ?? 0);
|
|
332
|
+
|
|
333
|
+
if (
|
|
334
|
+
shouldOpenTourSchedulerFromUrl() &&
|
|
335
|
+
(this.enabledChatWidgets.sstDesktop || this.enabledChatWidgets.sstMobile)
|
|
336
|
+
) {
|
|
337
|
+
this.openTourSchedulerOnLoad = true;
|
|
338
|
+
} else if (this.shouldAutoOpenChat(this.webchatConfigHasAutoOpenChat)) {
|
|
325
339
|
this.displayPubnubChat = true;
|
|
326
340
|
this.hideLauncher = true;
|
|
327
341
|
this.hasMounted = true;
|
|
328
342
|
this.updateAlreadyAutoOpenedTimestamp();
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
this.isLoading = false;
|
|
332
|
-
|
|
333
|
-
if (localStorage.getItem("isChatOpen") === "true") {
|
|
343
|
+
} else if (localStorage.getItem("isChatOpen") === "true") {
|
|
334
344
|
this.hideLauncher = true;
|
|
335
345
|
this.displayPubnubChat = true;
|
|
336
346
|
}
|
|
347
|
+
|
|
348
|
+
this.isLoading = false;
|
|
337
349
|
};
|
|
338
350
|
|
|
339
351
|
// The general info for the buildingg
|
|
@@ -1080,6 +1092,7 @@ export class MEChat extends LitElement {
|
|
|
1080
1092
|
virtualToursTypeOffered="${this.buildingWebchatView
|
|
1081
1093
|
.virtualToursTypeOffered ?? ""}"
|
|
1082
1094
|
.showTourNextToChat="${this.showTourNextToChat ?? ""}"
|
|
1095
|
+
.openSSTWindowOnLoad=${this.openTourSchedulerOnLoad}
|
|
1083
1096
|
@closeShowTourNextToChat=${() => {
|
|
1084
1097
|
this.showTourNextToChat = false;
|
|
1085
1098
|
this.hideLauncher = true;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { expect } from "@esm-bundle/chai";
|
|
2
|
+
import {
|
|
3
|
+
readGoogleReserveReferral,
|
|
4
|
+
shouldOpenTourSchedulerFromUrl,
|
|
5
|
+
storeGoogleReserveReferral,
|
|
6
|
+
} from "./googleReserve";
|
|
7
|
+
|
|
8
|
+
const STORAGE_KEY = "com.eliseai.webchat.googlereserve.referral";
|
|
9
|
+
|
|
10
|
+
const visit = (search: string): void =>
|
|
11
|
+
history.replaceState(null, "", `${location.pathname}${search}`);
|
|
12
|
+
|
|
13
|
+
describe("Google Reserve", () => {
|
|
14
|
+
const originalSearch = location.search;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
localStorage.removeItem(STORAGE_KEY);
|
|
22
|
+
visit(originalSearch);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("remembers a click from a Google listing, keeping the token intact", () => {
|
|
26
|
+
visit("?elise_open=tour&rwg_token=AFd1x%3D%3D");
|
|
27
|
+
storeGoogleReserveReferral(7);
|
|
28
|
+
visit("");
|
|
29
|
+
|
|
30
|
+
expect(readGoogleReserveReferral()).to.include({
|
|
31
|
+
rwgToken: "AFd1x==",
|
|
32
|
+
buildingId: 7,
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("has no referral without a token or once it has expired", () => {
|
|
37
|
+
visit("?utm_source=website");
|
|
38
|
+
storeGoogleReserveReferral(7);
|
|
39
|
+
expect(readGoogleReserveReferral()).to.equal(null);
|
|
40
|
+
|
|
41
|
+
localStorage.setItem(
|
|
42
|
+
STORAGE_KEY,
|
|
43
|
+
JSON.stringify({
|
|
44
|
+
rwgToken: "AFd1x==",
|
|
45
|
+
buildingId: 7,
|
|
46
|
+
expiresAt: Date.now() - 1,
|
|
47
|
+
})
|
|
48
|
+
);
|
|
49
|
+
expect(readGoogleReserveReferral()).to.equal(null);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("opens the tour scheduler only when the URL asks for it", () => {
|
|
53
|
+
visit("?elise_open=tour");
|
|
54
|
+
expect(shouldOpenTourSchedulerFromUrl()).to.equal(true);
|
|
55
|
+
visit("?elise_open=chat");
|
|
56
|
+
expect(shouldOpenTourSchedulerFromUrl()).to.equal(false);
|
|
57
|
+
visit("");
|
|
58
|
+
expect(shouldOpenTourSchedulerFromUrl()).to.equal(false);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Google requires the referral token kept for 30 days after the click.
|
|
2
|
+
const REFERRAL_TTL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
3
|
+
const REFERRAL_STORAGE_KEY = "com.eliseai.webchat.googlereserve.referral";
|
|
4
|
+
// Google "Book" links to a customer's page add this so the widget opens the tour scheduler.
|
|
5
|
+
const OPEN_PARAM = "elise_open";
|
|
6
|
+
|
|
7
|
+
type GoogleReserveReferral = {
|
|
8
|
+
rwgToken: string;
|
|
9
|
+
buildingId: number;
|
|
10
|
+
expiresAt: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const shouldOpenTourSchedulerFromUrl = (): boolean =>
|
|
14
|
+
new URLSearchParams(window.location.search).get(OPEN_PARAM) === "tour";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Remembers a click from a building's Google listing, which arrives with an
|
|
18
|
+
* `rwg_token` query param, so a booking within 30 days can be reported back.
|
|
19
|
+
*/
|
|
20
|
+
export const storeGoogleReserveReferral = (buildingId: number): void => {
|
|
21
|
+
const rwgToken = new URLSearchParams(window.location.search).get("rwg_token");
|
|
22
|
+
if (!rwgToken || !buildingId) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const referral: GoogleReserveReferral = {
|
|
26
|
+
rwgToken,
|
|
27
|
+
buildingId,
|
|
28
|
+
expiresAt: Date.now() + REFERRAL_TTL_MS,
|
|
29
|
+
};
|
|
30
|
+
localStorage.setItem(REFERRAL_STORAGE_KEY, JSON.stringify(referral));
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The visitor's click from a building's Google listing within the last 30 days,
|
|
35
|
+
* sent with a booking so the backend can report it to Google.
|
|
36
|
+
*/
|
|
37
|
+
export const readGoogleReserveReferral = (): GoogleReserveReferral | null => {
|
|
38
|
+
try {
|
|
39
|
+
const referral: GoogleReserveReferral | null = JSON.parse(
|
|
40
|
+
localStorage.getItem(REFERRAL_STORAGE_KEY) ?? "null"
|
|
41
|
+
);
|
|
42
|
+
return referral?.rwgToken && Date.now() < referral.expiresAt
|
|
43
|
+
? referral
|
|
44
|
+
: null;
|
|
45
|
+
} catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
};
|