@meetelise/chat 1.42.2 → 1.42.4
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/MyPubnub.d.ts +3 -1
- package/dist/src/WebComponent/LeadSourceMultitouchClient.d.ts +36 -0
- package/dist/src/WebComponent/Scheduler/tour-scheduler.d.ts +1 -0
- package/dist/src/WebComponent/actions/call-us-window.d.ts +1 -0
- package/dist/src/WebComponent/actions/email-us-window.d.ts +1 -0
- package/dist/src/WebComponent/launcher/Launcher.d.ts +1 -0
- package/dist/src/WebComponent/me-chat.d.ts +1 -0
- package/package.json +1 -1
- package/public/dist/index.js +282 -278
- package/src/MyPubnub.ts +12 -1
- package/src/WebComponent/FeeCalculator/components/addons/addon-table/table-matrix-qty-selector.ts +9 -3
- package/src/WebComponent/FeeCalculator/model/building-fee-view.ts +1 -1
- package/src/WebComponent/LeadSourceMultitouchClient.ts +222 -0
- package/src/WebComponent/Scheduler/tour-scheduler.ts +17 -1
- package/src/WebComponent/actions/call-us-window.ts +20 -3
- package/src/WebComponent/actions/email-us-window.ts +24 -3
- package/src/WebComponent/health-chat.ts +1 -0
- package/src/WebComponent/launcher/Launcher.ts +7 -0
- package/src/WebComponent/me-chat.ts +25 -6
- package/src/WebComponent/utilities-chat.ts +1 -0
package/src/MyPubnub.ts
CHANGED
|
@@ -6,9 +6,10 @@ import { LogType, sendLoggingEvent } from "./analytics";
|
|
|
6
6
|
import { ChatStorageKey, createChatStorageKey } from "./handleChatId";
|
|
7
7
|
import LeadSourceClient from "./WebComponent/LeadSourceClient";
|
|
8
8
|
import { pushGtmEvent } from "./gtm";
|
|
9
|
-
import { isContainingEmail } from "./utils";
|
|
9
|
+
import { isContainingEmail, snakify } from "./utils";
|
|
10
10
|
import { WidgetType } from "./main/MEChat";
|
|
11
11
|
import { BuildingWebchatView } from "./fetchBuildingWebchatView";
|
|
12
|
+
import { LeadSourceMultitouchClient } from "./WebComponent/LeadSourceMultitouchClient";
|
|
12
13
|
|
|
13
14
|
interface TokenResponse {
|
|
14
15
|
auth: {
|
|
@@ -94,6 +95,8 @@ class MyPubnub {
|
|
|
94
95
|
private apiHost = "https://app.meetelise.com";
|
|
95
96
|
|
|
96
97
|
private leadSourceClient: LeadSourceClient | null = null;
|
|
98
|
+
private leadSourceMultitouchClient: LeadSourceMultitouchClient | null = null;
|
|
99
|
+
|
|
97
100
|
private buildingWebchatView: BuildingWebchatView | null = null;
|
|
98
101
|
private buildingSlug: string;
|
|
99
102
|
private orgSlug: string;
|
|
@@ -188,6 +191,7 @@ class MyPubnub {
|
|
|
188
191
|
orgSlug: string,
|
|
189
192
|
leadSource: string | null = null,
|
|
190
193
|
leadUserId: string,
|
|
194
|
+
leadSourceMultitouchClient: LeadSourceMultitouchClient | null,
|
|
191
195
|
leadSourceClient: LeadSourceClient | null = null,
|
|
192
196
|
widgetType: WidgetType = WidgetType.Default
|
|
193
197
|
) {
|
|
@@ -198,6 +202,7 @@ class MyPubnub {
|
|
|
198
202
|
this.leadUserId = leadUserId;
|
|
199
203
|
this.channel = `webchat_${leadUserId}`;
|
|
200
204
|
this.leadSourceClient = leadSourceClient;
|
|
205
|
+
this.leadSourceMultitouchClient = leadSourceMultitouchClient;
|
|
201
206
|
this.widgetType = widgetType;
|
|
202
207
|
}
|
|
203
208
|
|
|
@@ -608,8 +613,14 @@ class MyPubnub {
|
|
|
608
613
|
leadSource: this.leadSource,
|
|
609
614
|
widgetType: this.widgetType,
|
|
610
615
|
isDevState: this.shouldCreateAsDevState(),
|
|
616
|
+
lead_sources_with_timestamps: (
|
|
617
|
+
this.leadSourceMultitouchClient?.getSafeLeadSourceTouchpointsWithDefault(
|
|
618
|
+
{ includedUserSelectedLeadSource: null }
|
|
619
|
+
) ?? []
|
|
620
|
+
).map((source) => snakify({ ...source })),
|
|
611
621
|
},
|
|
612
622
|
});
|
|
623
|
+
this.leadSourceMultitouchClient?.resetLeadSourceTouchpoints();
|
|
613
624
|
}
|
|
614
625
|
|
|
615
626
|
if (!this.isFirstChatMessageSent) {
|
package/src/WebComponent/FeeCalculator/components/addons/addon-table/table-matrix-qty-selector.ts
CHANGED
|
@@ -145,16 +145,20 @@ export class TableMatrixQtySelector extends LitElement {
|
|
|
145
145
|
.join(" ");
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
private renderItemType(type: string): TemplateResult {
|
|
148
|
+
private renderItemType(type: string, isSingleItem: boolean): TemplateResult {
|
|
149
149
|
const quantity = this.quantities[type] ?? 0;
|
|
150
150
|
const maxQty = this.getMaxQuantityForType(type);
|
|
151
151
|
const canIncrement =
|
|
152
152
|
this.isValidCombination(type, quantity + 1) && quantity < maxQty;
|
|
153
153
|
const formattedType = this.formatItemType(type);
|
|
154
154
|
|
|
155
|
+
const showTypeLabel = !isSingleItem;
|
|
156
|
+
|
|
155
157
|
return html`
|
|
156
158
|
<div class="item-type-row">
|
|
157
|
-
|
|
159
|
+
${showTypeLabel
|
|
160
|
+
? html`<div class="item-label">${formattedType}:</div>`
|
|
161
|
+
: html`<div></div>`}
|
|
158
162
|
<div class="quantity-control ${this.disabled ? "unavailable" : ""}">
|
|
159
163
|
<button
|
|
160
164
|
class="quantity-button"
|
|
@@ -188,9 +192,11 @@ export class TableMatrixQtySelector extends LitElement {
|
|
|
188
192
|
const types = this.itemTypes;
|
|
189
193
|
if (!types.length) return html``;
|
|
190
194
|
|
|
195
|
+
const isSingleItem = types.length === 1;
|
|
196
|
+
|
|
191
197
|
return html`
|
|
192
198
|
<div class="matrix-container">
|
|
193
|
-
${types.map((type) => this.renderItemType(type))}
|
|
199
|
+
${types.map((type) => this.renderItemType(type, isSingleItem))}
|
|
194
200
|
</div>
|
|
195
201
|
`;
|
|
196
202
|
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import addDays from "date-fns/addDays";
|
|
2
|
+
import formatISO from "date-fns/formatISO";
|
|
3
|
+
import parseISO from "date-fns/parseISO";
|
|
4
|
+
import { getCampaignSources, LogType, sendLoggingEvent } from "../analytics";
|
|
5
|
+
import { getUrlQueryParameters } from "../postLeadSources";
|
|
6
|
+
import { getDefaultLeadSourceAttribution } from "./LeadSourceClient";
|
|
7
|
+
|
|
8
|
+
interface LeadSourceParameters {
|
|
9
|
+
websiteOrigin: string | null;
|
|
10
|
+
websiteSearch: string | null;
|
|
11
|
+
queryParameters: {
|
|
12
|
+
[queryKey: string]: string;
|
|
13
|
+
} | null;
|
|
14
|
+
referrer: string | null;
|
|
15
|
+
parsedUtmSource: string | null;
|
|
16
|
+
campaignSources: string[] | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface LeadSourceSubmittedListItem {
|
|
20
|
+
timestampInitiallyLogged: string;
|
|
21
|
+
leadSourceValue: string | null;
|
|
22
|
+
type: "default" | "touchpoint" | "user-selected";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface LeadSourceValueWithTimestamp
|
|
26
|
+
extends LeadSourceSubmittedListItem {
|
|
27
|
+
parameters: LeadSourceParameters | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
Stored in local storage as a json of
|
|
32
|
+
{
|
|
33
|
+
timestampExpires: string,
|
|
34
|
+
leadSources: LeadSourceValueWithTimestamp[]
|
|
35
|
+
}
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
export class LeadSourceMultitouchClient {
|
|
39
|
+
constructor(orgSlug: string, buildingSlug: string) {
|
|
40
|
+
this.orgSlug = orgSlug;
|
|
41
|
+
this.buildingSlug = buildingSlug;
|
|
42
|
+
}
|
|
43
|
+
orgSlug: string;
|
|
44
|
+
buildingSlug: string;
|
|
45
|
+
|
|
46
|
+
private persistLeadSourceTTLDays = 30;
|
|
47
|
+
private maxSourcesNonPropertyWebsiteCount = 3; // 3 based on vibes from the team
|
|
48
|
+
|
|
49
|
+
private _generateLeadSourceLocalStorageKey = (): string => {
|
|
50
|
+
return `com.eliseai.webchat.leadsources.v2.buildingslug=${this.buildingSlug}`;
|
|
51
|
+
};
|
|
52
|
+
private _generateNewExpirationTimestamp = (): string => {
|
|
53
|
+
return formatISO(addDays(new Date(), this.persistLeadSourceTTLDays));
|
|
54
|
+
};
|
|
55
|
+
private _generateLeadSourceParameters = () => {
|
|
56
|
+
const queryParameters = getUrlQueryParameters();
|
|
57
|
+
return {
|
|
58
|
+
websiteOrigin: window.location.origin,
|
|
59
|
+
websiteSearch: window.location.search,
|
|
60
|
+
queryParameters: queryParameters,
|
|
61
|
+
referrer: document.referrer,
|
|
62
|
+
parsedUtmSource: queryParameters ? queryParameters["utm_source"] : null,
|
|
63
|
+
campaignSources: Object.values(getCampaignSources()).filter(
|
|
64
|
+
(source) => source
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
addSafeLeadSourceTouchpoint = (leadSourceValue: string): void => {
|
|
70
|
+
const leadSourceLocalStorageParsed = this.getLocalStorageMultitouchValue();
|
|
71
|
+
const leadSourceLocalStorageKey = this._generateLeadSourceLocalStorageKey();
|
|
72
|
+
if (
|
|
73
|
+
!leadSourceLocalStorageParsed ||
|
|
74
|
+
this.isExpiredTimestamp(leadSourceLocalStorageParsed.timestampExpires)
|
|
75
|
+
) {
|
|
76
|
+
const newMultitouchLeadSourceInfo: {
|
|
77
|
+
timestampExpires: string;
|
|
78
|
+
leadSources: LeadSourceValueWithTimestamp[];
|
|
79
|
+
} = {
|
|
80
|
+
timestampExpires: this._generateNewExpirationTimestamp(),
|
|
81
|
+
leadSources: [
|
|
82
|
+
{
|
|
83
|
+
parameters: this._generateLeadSourceParameters(),
|
|
84
|
+
leadSourceValue: leadSourceValue,
|
|
85
|
+
timestampInitiallyLogged: formatISO(new Date()),
|
|
86
|
+
type: "touchpoint",
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
};
|
|
90
|
+
localStorage.setItem(
|
|
91
|
+
leadSourceLocalStorageKey,
|
|
92
|
+
JSON.stringify(newMultitouchLeadSourceInfo)
|
|
93
|
+
);
|
|
94
|
+
} else {
|
|
95
|
+
// check if source already exists
|
|
96
|
+
const existingLeadSource = leadSourceLocalStorageParsed.leadSources.find(
|
|
97
|
+
(source) => source.leadSourceValue === leadSourceValue
|
|
98
|
+
);
|
|
99
|
+
if (existingLeadSource) {
|
|
100
|
+
// if it already exists, we dont need to add again or update timestamp!
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (
|
|
104
|
+
leadSourceLocalStorageParsed.leadSources.length <
|
|
105
|
+
this.maxSourcesNonPropertyWebsiteCount
|
|
106
|
+
) {
|
|
107
|
+
// if we have enough space, can add
|
|
108
|
+
leadSourceLocalStorageParsed.leadSources.push({
|
|
109
|
+
parameters: this._generateLeadSourceParameters(),
|
|
110
|
+
leadSourceValue: leadSourceValue,
|
|
111
|
+
timestampInitiallyLogged: formatISO(new Date()),
|
|
112
|
+
type: "touchpoint",
|
|
113
|
+
});
|
|
114
|
+
leadSourceLocalStorageParsed.timestampExpires =
|
|
115
|
+
this._generateNewExpirationTimestamp();
|
|
116
|
+
localStorage.setItem(
|
|
117
|
+
leadSourceLocalStorageKey,
|
|
118
|
+
JSON.stringify(leadSourceLocalStorageParsed)
|
|
119
|
+
);
|
|
120
|
+
return;
|
|
121
|
+
} else {
|
|
122
|
+
// eslint-disable-next-line no-console
|
|
123
|
+
console.warn(
|
|
124
|
+
`Too many lead sources for ${this.buildingSlug}, max is ${this.maxSourcesNonPropertyWebsiteCount}`
|
|
125
|
+
);
|
|
126
|
+
sendLoggingEvent({
|
|
127
|
+
logType: LogType.warn,
|
|
128
|
+
buildingSlug: this.buildingSlug,
|
|
129
|
+
orgSlug: this.orgSlug,
|
|
130
|
+
logTitle: "TOO_MANY_LEAD_SOURCES",
|
|
131
|
+
logData: {
|
|
132
|
+
buildingSlug: this.buildingSlug,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
getSafeLeadSourceTouchpointsWithDefault = ({
|
|
140
|
+
includedUserSelectedLeadSource,
|
|
141
|
+
}: {
|
|
142
|
+
includedUserSelectedLeadSource: string | null;
|
|
143
|
+
}): LeadSourceSubmittedListItem[] => {
|
|
144
|
+
const leadSourcesParsed = this.getLocalStorageMultitouchValue();
|
|
145
|
+
const defaultLeadSource = getDefaultLeadSourceAttribution(this.orgSlug);
|
|
146
|
+
if (!leadSourcesParsed) {
|
|
147
|
+
const defaultedList: LeadSourceSubmittedListItem[] = [
|
|
148
|
+
{
|
|
149
|
+
leadSourceValue: defaultLeadSource,
|
|
150
|
+
timestampInitiallyLogged: formatISO(new Date()),
|
|
151
|
+
type: "default",
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
if (includedUserSelectedLeadSource) {
|
|
155
|
+
defaultedList.push({
|
|
156
|
+
leadSourceValue: includedUserSelectedLeadSource,
|
|
157
|
+
timestampInitiallyLogged: formatISO(new Date()),
|
|
158
|
+
type: "user-selected",
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return defaultedList;
|
|
162
|
+
}
|
|
163
|
+
const oldestTimestamp =
|
|
164
|
+
leadSourcesParsed.leadSources.length > 0
|
|
165
|
+
? leadSourcesParsed.leadSources.sort(
|
|
166
|
+
(a, b) =>
|
|
167
|
+
parseISO(a.timestampInitiallyLogged).getTime() -
|
|
168
|
+
parseISO(b.timestampInitiallyLogged).getTime()
|
|
169
|
+
)[0].timestampInitiallyLogged
|
|
170
|
+
: formatISO(new Date());
|
|
171
|
+
|
|
172
|
+
const parsedList: LeadSourceSubmittedListItem[] = [
|
|
173
|
+
{
|
|
174
|
+
timestampInitiallyLogged: oldestTimestamp,
|
|
175
|
+
leadSourceValue: defaultLeadSource,
|
|
176
|
+
type: "default",
|
|
177
|
+
},
|
|
178
|
+
...leadSourcesParsed.leadSources.map((source) => ({
|
|
179
|
+
timestampInitiallyLogged: source.timestampInitiallyLogged,
|
|
180
|
+
leadSourceValue: source.leadSourceValue,
|
|
181
|
+
type: source.type,
|
|
182
|
+
})),
|
|
183
|
+
];
|
|
184
|
+
if (includedUserSelectedLeadSource) {
|
|
185
|
+
parsedList.push({
|
|
186
|
+
leadSourceValue: includedUserSelectedLeadSource,
|
|
187
|
+
timestampInitiallyLogged: formatISO(new Date()),
|
|
188
|
+
type: "user-selected",
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return parsedList;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
private getLocalStorageMultitouchValue = (): {
|
|
195
|
+
timestampExpires: string;
|
|
196
|
+
leadSources: LeadSourceValueWithTimestamp[];
|
|
197
|
+
} | null => {
|
|
198
|
+
const leadSourceKey = this._generateLeadSourceLocalStorageKey();
|
|
199
|
+
const leadSourceRawValue = localStorage.getItem(leadSourceKey);
|
|
200
|
+
|
|
201
|
+
if (!leadSourceRawValue) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
const leadSourcesParsed: {
|
|
205
|
+
timestampExpires: string;
|
|
206
|
+
leadSources: LeadSourceValueWithTimestamp[];
|
|
207
|
+
} = JSON.parse(leadSourceRawValue);
|
|
208
|
+
return leadSourcesParsed;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
private isExpiredTimestamp = (timestamp: string) => {
|
|
212
|
+
const timestampExpires = parseISO(timestamp);
|
|
213
|
+
const now = new Date();
|
|
214
|
+
return timestampExpires < now;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
resetLeadSourceTouchpoints = (): boolean => {
|
|
218
|
+
const leadSourceKey = this._generateLeadSourceLocalStorageKey();
|
|
219
|
+
localStorage.removeItem(leadSourceKey);
|
|
220
|
+
return true;
|
|
221
|
+
};
|
|
222
|
+
}
|
|
@@ -28,7 +28,7 @@ import { DatePicker } from "./date-picker";
|
|
|
28
28
|
import { MESelect } from "../me-select";
|
|
29
29
|
import { TimePicker } from "./time-picker";
|
|
30
30
|
import { LabeledOption } from "../../fetchBuildingInfo";
|
|
31
|
-
import { isMobile, isValidPhoneNumber } from "../../utils";
|
|
31
|
+
import { isMobile, isValidPhoneNumber, snakify } from "../../utils";
|
|
32
32
|
import axios, { AxiosError } from "axios";
|
|
33
33
|
import mapValues from "lodash/mapValues";
|
|
34
34
|
import classnames from "classnames";
|
|
@@ -54,6 +54,7 @@ import formatInTimeZone from "date-fns-tz/formatInTimeZone";
|
|
|
54
54
|
import { getTimezoneAbbreviation } from "../../getTimezoneString";
|
|
55
55
|
import startOfDay from "date-fns/startOfDay";
|
|
56
56
|
import isSameDay from "date-fns/isSameDay";
|
|
57
|
+
import { LeadSourceMultitouchClient } from "../LeadSourceMultitouchClient";
|
|
57
58
|
|
|
58
59
|
@customElement("tour-scheduler")
|
|
59
60
|
export class TourScheduler extends LitElement {
|
|
@@ -87,6 +88,9 @@ export class TourScheduler extends LitElement {
|
|
|
87
88
|
@property({ attribute: true })
|
|
88
89
|
private leadSourceClient: LeadSourceClient | null = null;
|
|
89
90
|
|
|
91
|
+
@property({ attribute: true })
|
|
92
|
+
private leadSourceMultitouchClient: LeadSourceMultitouchClient | null = null;
|
|
93
|
+
|
|
90
94
|
@property({ attribute: true })
|
|
91
95
|
buildingName = "";
|
|
92
96
|
|
|
@@ -649,6 +653,17 @@ export class TourScheduler extends LitElement {
|
|
|
649
653
|
],
|
|
650
654
|
query_params: Object.fromEntries(queryParams.entries()),
|
|
651
655
|
conversation_tracking_id: this.leadSourceClient?.chatId,
|
|
656
|
+
lead_sources_with_timestamps: (
|
|
657
|
+
this.leadSourceMultitouchClient?.getSafeLeadSourceTouchpointsWithDefault(
|
|
658
|
+
{
|
|
659
|
+
includedUserSelectedLeadSource:
|
|
660
|
+
this.selectedLeadSource?.value &&
|
|
661
|
+
this.selectedLeadSource.value.length > 0
|
|
662
|
+
? this.selectedLeadSource.value
|
|
663
|
+
: null,
|
|
664
|
+
}
|
|
665
|
+
) ?? []
|
|
666
|
+
).map((source) => snakify({ ...source })),
|
|
652
667
|
};
|
|
653
668
|
|
|
654
669
|
const url = `https://app.meetelise.com/platformApi/state/create/v2/scheduleMe`;
|
|
@@ -666,6 +681,7 @@ export class TourScheduler extends LitElement {
|
|
|
666
681
|
webchatAction: "tour-scheduler",
|
|
667
682
|
stateId: null,
|
|
668
683
|
});
|
|
684
|
+
this.leadSourceMultitouchClient?.resetLeadSourceTouchpoints();
|
|
669
685
|
this.isSubmitting = false;
|
|
670
686
|
this.tourIsBooked = true;
|
|
671
687
|
} catch (e: unknown) {
|
|
@@ -4,11 +4,15 @@ import { customElement, property, state } from "lit/decorators.js";
|
|
|
4
4
|
import { classMap } from "lit/directives/class-map.js";
|
|
5
5
|
import { createRef, ref, Ref } from "lit/directives/ref.js";
|
|
6
6
|
import { pushGtmEvent } from "../../gtm";
|
|
7
|
-
import { isMobile } from "../../utils";
|
|
7
|
+
import { isMobile, snakify } from "../../utils";
|
|
8
8
|
import { PhoneOutlineIcon } from "../icons/PhoneOutlineIcon";
|
|
9
9
|
import LeadSourceClient, {
|
|
10
10
|
getDefaultLeadSourceAttribution,
|
|
11
11
|
} from "../LeadSourceClient";
|
|
12
|
+
import {
|
|
13
|
+
LeadSourceMultitouchClient,
|
|
14
|
+
LeadSourceSubmittedListItem,
|
|
15
|
+
} from "../LeadSourceMultitouchClient";
|
|
12
16
|
|
|
13
17
|
import { getOfficeHourText } from "../OfficeHours";
|
|
14
18
|
import {
|
|
@@ -166,6 +170,9 @@ export class CallUsWindow extends LitElement {
|
|
|
166
170
|
@property({ attribute: true })
|
|
167
171
|
private leadSourceClient: LeadSourceClient | null = null;
|
|
168
172
|
|
|
173
|
+
@property({ attribute: true })
|
|
174
|
+
private leadSourceMultitouchClient: LeadSourceMultitouchClient | null = null;
|
|
175
|
+
|
|
169
176
|
phoneNumberInputRef: Ref<HTMLInputElement> = createRef();
|
|
170
177
|
|
|
171
178
|
@state()
|
|
@@ -235,12 +242,18 @@ export class CallUsWindow extends LitElement {
|
|
|
235
242
|
: [getDefaultLeadSourceAttribution(this.orgSlug)]
|
|
236
243
|
),
|
|
237
244
|
],
|
|
238
|
-
this.leadSourceClient?.chatId
|
|
245
|
+
this.leadSourceClient?.chatId,
|
|
246
|
+
this.leadSourceMultitouchClient?.getSafeLeadSourceTouchpointsWithDefault(
|
|
247
|
+
{
|
|
248
|
+
includedUserSelectedLeadSource: null,
|
|
249
|
+
}
|
|
250
|
+
)
|
|
239
251
|
);
|
|
240
252
|
this.leadSourceClient?.checkAndHandleForLogLeadSource({
|
|
241
253
|
webchatAction: "text-us",
|
|
242
254
|
stateId: null,
|
|
243
255
|
});
|
|
256
|
+
this.leadSourceMultitouchClient?.resetLeadSourceTouchpoints();
|
|
244
257
|
this.hasSubmittedForm = true;
|
|
245
258
|
this.submittingTextUsOption = false;
|
|
246
259
|
} catch (e) {
|
|
@@ -428,7 +441,8 @@ const createTextWithUs = async (
|
|
|
428
441
|
orgSlug: string,
|
|
429
442
|
buildingSlug: string,
|
|
430
443
|
leadSources: string[],
|
|
431
|
-
chatId?: string | null
|
|
444
|
+
chatId?: string | null,
|
|
445
|
+
leadSourcesWithTimestamps?: LeadSourceSubmittedListItem[]
|
|
432
446
|
) => {
|
|
433
447
|
const formattedPhoneNumber =
|
|
434
448
|
"+1" +
|
|
@@ -447,6 +461,9 @@ const createTextWithUs = async (
|
|
|
447
461
|
// @ts-ignore
|
|
448
462
|
query_params: Object.fromEntries(queryParams.entries()),
|
|
449
463
|
conversation_tracking_id: chatId,
|
|
464
|
+
lead_sources_with_timestamps: (leadSourcesWithTimestamps ?? []).map(
|
|
465
|
+
(source) => snakify({ ...source })
|
|
466
|
+
),
|
|
450
467
|
};
|
|
451
468
|
pushGtmEvent("textUsSubmitted", {
|
|
452
469
|
phone: formattedPhoneNumber,
|
|
@@ -16,10 +16,14 @@ import axios from "axios";
|
|
|
16
16
|
import { FeatureFlagsShowDropdown } from "../../fetchFeatureFlag";
|
|
17
17
|
import { pushGtmEvent } from "../../gtm";
|
|
18
18
|
import formDisclaimer from "../../disclaimers";
|
|
19
|
-
import { isMobile } from "../../utils";
|
|
19
|
+
import { isMobile, snakify } from "../../utils";
|
|
20
20
|
import LeadSourceClient, {
|
|
21
21
|
getDefaultLeadSourceAttribution,
|
|
22
22
|
} from "../LeadSourceClient";
|
|
23
|
+
import {
|
|
24
|
+
LeadSourceMultitouchClient,
|
|
25
|
+
LeadSourceSubmittedListItem,
|
|
26
|
+
} from "../LeadSourceMultitouchClient";
|
|
23
27
|
|
|
24
28
|
@customElement("email-us-window")
|
|
25
29
|
export class EmailUsWindow extends LitElement {
|
|
@@ -120,6 +124,9 @@ export class EmailUsWindow extends LitElement {
|
|
|
120
124
|
@property({ attribute: true })
|
|
121
125
|
private leadSourceClient: LeadSourceClient | null = null;
|
|
122
126
|
|
|
127
|
+
@property({ attribute: true })
|
|
128
|
+
private leadSourceMultitouchClient: LeadSourceMultitouchClient | null = null;
|
|
129
|
+
|
|
123
130
|
@property({ attribute: true })
|
|
124
131
|
featureFlagShowDropdown = "";
|
|
125
132
|
|
|
@@ -275,12 +282,22 @@ export class EmailUsWindow extends LitElement {
|
|
|
275
282
|
: [getDefaultLeadSourceAttribution(this.orgSlug)]
|
|
276
283
|
),
|
|
277
284
|
],
|
|
278
|
-
this.leadSourceClient?.chatId
|
|
285
|
+
this.leadSourceClient?.chatId,
|
|
286
|
+
this.leadSourceMultitouchClient?.getSafeLeadSourceTouchpointsWithDefault(
|
|
287
|
+
{
|
|
288
|
+
includedUserSelectedLeadSource:
|
|
289
|
+
this.selectedLeadSource?.value &&
|
|
290
|
+
this.selectedLeadSource.value.length > 0
|
|
291
|
+
? this.selectedLeadSource.value
|
|
292
|
+
: null,
|
|
293
|
+
}
|
|
294
|
+
)
|
|
279
295
|
);
|
|
280
296
|
this.leadSourceClient?.checkAndHandleForLogLeadSource({
|
|
281
297
|
webchatAction: "email-us",
|
|
282
298
|
stateId: null,
|
|
283
299
|
});
|
|
300
|
+
this.leadSourceMultitouchClient?.resetLeadSourceTouchpoints();
|
|
284
301
|
this.hasSubmittedForm = true;
|
|
285
302
|
this.isSubmitting = false;
|
|
286
303
|
// Remove the height of the button when it leaves the loading state
|
|
@@ -509,7 +526,8 @@ const createEmail = async (
|
|
|
509
526
|
orgSlug: string,
|
|
510
527
|
buildingSlug: string,
|
|
511
528
|
leadSources: string[],
|
|
512
|
-
chatId?: string | null
|
|
529
|
+
chatId?: string | null,
|
|
530
|
+
leadSourcesWithTimestamps?: LeadSourceSubmittedListItem[]
|
|
513
531
|
) => {
|
|
514
532
|
const formattedPhoneNumber =
|
|
515
533
|
"+1" +
|
|
@@ -532,6 +550,9 @@ const createEmail = async (
|
|
|
532
550
|
// @ts-ignore
|
|
533
551
|
query_params: Object.fromEntries(queryParams.entries()),
|
|
534
552
|
conversation_tracking_id: chatId,
|
|
553
|
+
lead_sources_with_timestamps: (leadSourcesWithTimestamps ?? []).map(
|
|
554
|
+
(source) => snakify({ ...source })
|
|
555
|
+
),
|
|
535
556
|
};
|
|
536
557
|
pushGtmEvent("emailUsSubmitted", {
|
|
537
558
|
firstName,
|
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
getRawAvailabilities,
|
|
46
46
|
resetAvailabilitiesCache,
|
|
47
47
|
} from "../../getAvailabilities";
|
|
48
|
+
import { LeadSourceMultitouchClient } from "../LeadSourceMultitouchClient";
|
|
48
49
|
|
|
49
50
|
@customElement("meetelise-launcher")
|
|
50
51
|
export class Launcher extends LitElement {
|
|
@@ -202,6 +203,9 @@ export class Launcher extends LitElement {
|
|
|
202
203
|
@property({ attribute: true })
|
|
203
204
|
private leadSourceClient: LeadSourceClient | null = null;
|
|
204
205
|
|
|
206
|
+
@state()
|
|
207
|
+
private leadSourceMultitouchClient: LeadSourceMultitouchClient | null = null;
|
|
208
|
+
|
|
205
209
|
@state()
|
|
206
210
|
isEmailWindowOpen = false;
|
|
207
211
|
@state()
|
|
@@ -1184,6 +1188,7 @@ export class Launcher extends LitElement {
|
|
|
1184
1188
|
.buildingId=${this.buildingId}
|
|
1185
1189
|
.buildingName=${this.buildingName}
|
|
1186
1190
|
.leadSourceClient=${this.leadSourceClient}
|
|
1191
|
+
.leadSourceMultitouchClient=${this.leadSourceMultitouchClient}
|
|
1187
1192
|
.orgLegalName=${this.orgLegalName}
|
|
1188
1193
|
>
|
|
1189
1194
|
</email-us-window>
|
|
@@ -1223,6 +1228,7 @@ export class Launcher extends LitElement {
|
|
|
1223
1228
|
? this.showTourNextToChat
|
|
1224
1229
|
: ""}
|
|
1225
1230
|
.leadSourceClient=${this.leadSourceClient}
|
|
1231
|
+
.leadSourceMultitouchClient=${this.leadSourceMultitouchClient}
|
|
1226
1232
|
${ref(this.tourSchedulerRef)}
|
|
1227
1233
|
></tour-scheduler>
|
|
1228
1234
|
</div>`
|
|
@@ -1252,6 +1258,7 @@ export class Launcher extends LitElement {
|
|
|
1252
1258
|
buildingName="${this.buildingName}"
|
|
1253
1259
|
orgSlug="${this.orgSlug}"
|
|
1254
1260
|
.leadSourceClient=${this.leadSourceClient}
|
|
1261
|
+
.leadSourceMultitouchClient=${this.leadSourceMultitouchClient}
|
|
1255
1262
|
.orgLegalName=${this.orgLegalName}
|
|
1256
1263
|
></call-us-window>
|
|
1257
1264
|
</div>
|
|
@@ -65,6 +65,7 @@ import { WidgetType } from "../main/MEChat";
|
|
|
65
65
|
import { replaceSelectButtonsWithNewLink } from "../replaceSelectButtonsWithNewLink";
|
|
66
66
|
|
|
67
67
|
import "./chat-additional-actions";
|
|
68
|
+
import { LeadSourceMultitouchClient } from "./LeadSourceMultitouchClient";
|
|
68
69
|
|
|
69
70
|
@customElement("me-chat")
|
|
70
71
|
export class MEChat extends LitElement {
|
|
@@ -179,7 +180,10 @@ export class MEChat extends LitElement {
|
|
|
179
180
|
private myPubnub: MyPubnub | null = null;
|
|
180
181
|
|
|
181
182
|
@state()
|
|
182
|
-
private LeadSourceClient: LeadSourceClient | null = null;
|
|
183
|
+
private LeadSourceClient: LeadSourceClient | null = null; // DEPRECATED IN FAVOR OF LeadSourceMultitouchClient
|
|
184
|
+
|
|
185
|
+
@state()
|
|
186
|
+
private LeadSourceMultitouchClient: LeadSourceMultitouchClient | null = null;
|
|
183
187
|
|
|
184
188
|
@state()
|
|
185
189
|
private sampleRateToUse = 0.05;
|
|
@@ -547,21 +551,35 @@ export class MEChat extends LitElement {
|
|
|
547
551
|
throw new Error("Lead ID is null");
|
|
548
552
|
}
|
|
549
553
|
this.LeadSourceClient = new LeadSourceClient();
|
|
554
|
+
|
|
555
|
+
this.LeadSourceMultitouchClient = new LeadSourceMultitouchClient(
|
|
556
|
+
this.orgSlug,
|
|
557
|
+
this.buildingSlug
|
|
558
|
+
);
|
|
559
|
+
|
|
550
560
|
this.myPubnub = new MyPubnub(
|
|
551
561
|
this.buildingSlug,
|
|
552
562
|
this.buildingWebchatView,
|
|
553
563
|
this.orgSlug,
|
|
554
564
|
null, // initialize lead source as null initially
|
|
555
565
|
updatedChatStorageKey.leadId,
|
|
566
|
+
this.LeadSourceMultitouchClient,
|
|
556
567
|
this.LeadSourceClient,
|
|
557
568
|
this.widgetType
|
|
558
569
|
);
|
|
559
570
|
this.LeadSourceClient.chatId = this.myPubnub.channel;
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
571
|
+
const generatedLeadSource =
|
|
572
|
+
await this.LeadSourceClient?.generateUserLeadSource({
|
|
573
|
+
leadId: this.myPubnub?.leadUserId ?? "",
|
|
574
|
+
orgSlug: this.orgSlug,
|
|
575
|
+
buildingSlug: this.buildingSlug,
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
if (generatedLeadSource) {
|
|
579
|
+
this.LeadSourceMultitouchClient.addSafeLeadSourceTouchpoint(
|
|
580
|
+
generatedLeadSource
|
|
581
|
+
);
|
|
582
|
+
}
|
|
565
583
|
|
|
566
584
|
// eslint-disable-next-line no-console
|
|
567
585
|
console.log(
|
|
@@ -961,6 +979,7 @@ export class MEChat extends LitElement {
|
|
|
961
979
|
.left=${this.left}
|
|
962
980
|
.right=${this.right}
|
|
963
981
|
.leadSourceClient=${this.LeadSourceClient}
|
|
982
|
+
.leadSourceMultitouchClient=${this.LeadSourceMultitouchClient}
|
|
964
983
|
>
|
|
965
984
|
</meetelise-launcher>`
|
|
966
985
|
: ""
|