Skip to content

Commit eed28a1

Browse files
authored
Merge pull request #2528 from ably/web-4261-hubspot-meta-tag
[WEB-4261] Open Hubspot chat when conversation Meta tag is present
2 parents c349429 + d643236 commit eed28a1

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

src/external-scripts/hubspot.test.ts

+61
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,65 @@ describe('Hubspot', () => {
9292
expect(spy).toHaveBeenCalledTimes(2);
9393
});
9494
});
95+
96+
describe('openFromMetaTag', () => {
97+
beforeEach(() => {
98+
document.head.innerHTML = '';
99+
jest.spyOn(window.history, 'pushState').mockImplementation();
100+
global.window.HubSpotConversations = {
101+
widget: {
102+
load: jest.fn(),
103+
open: jest.fn(),
104+
},
105+
};
106+
});
107+
108+
afterEach(() => {
109+
jest.restoreAllMocks();
110+
});
111+
112+
it('opens chat widget when conversation meta tag exists', () => {
113+
// Add a meta tag to the document
114+
const metaTag = document.createElement('meta');
115+
metaTag.name = 'conversation';
116+
metaTag.content = 'sales';
117+
document.head.appendChild(metaTag);
118+
119+
hubspot('12345');
120+
121+
// Simulate the HubSpot script loading by calling the registered callback
122+
global.hsConversationsOnReady[0]();
123+
124+
expect(window.history.pushState).toHaveBeenCalledWith({}, '', '?chat-type=sales');
125+
expect(global.window.HubSpotConversations.widget.load).toHaveBeenCalled();
126+
expect(global.window.HubSpotConversations.widget.open).toHaveBeenCalled();
127+
});
128+
129+
it('does not open chat widget when no conversation meta tag exists', () => {
130+
document.head.innerHTML = '<meta name="other-tag" content="something">';
131+
132+
hubspot('12345');
133+
134+
// Simulate the HubSpot script loading
135+
global.hsConversationsOnReady[0]();
136+
137+
expect(window.history.pushState).not.toHaveBeenCalled();
138+
expect(global.window.HubSpotConversations.widget.load).not.toHaveBeenCalled();
139+
expect(global.window.HubSpotConversations.widget.open).not.toHaveBeenCalled();
140+
});
141+
142+
it('correctly sets URL query parameter from meta tag content', () => {
143+
const metaTag = document.createElement('meta');
144+
metaTag.name = 'conversation';
145+
metaTag.content = 'support';
146+
document.head.appendChild(metaTag);
147+
148+
hubspot('12345');
149+
150+
// Simulate the HubSpot script loading
151+
global.hsConversationsOnReady[0]();
152+
153+
expect(window.history.pushState).toHaveBeenCalledWith({}, '', '?chat-type=support');
154+
});
155+
});
95156
});

src/external-scripts/hubspot.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ declare global {
66
type HubspotItem = string | Record<string, string>;
77
interface Window {
88
_hsq: Array<string | Record<string, string>>[];
9+
hsConversationsSettings?: {
10+
loadImmediately: boolean;
11+
};
12+
hsConversationsOnReady?: Array<() => void>;
913
}
1014
}
1115

@@ -22,12 +26,25 @@ export type HubspotUser = {
2226
adminUrl: string;
2327
};
2428

25-
const hubspot = (hubspotTrackingId, loadImmediately = true) => {
29+
const hubspot = (hubspotTrackingId: string, loadImmediately = true) => {
30+
const openFromMetaTag = () => {
31+
const metaConversation = document.querySelector('meta[name="conversation"]') as HTMLMetaElement;
32+
33+
if (metaConversation) {
34+
window.history.pushState({}, '', `?chat-type=${metaConversation.content}`);
35+
36+
window.HubSpotConversations?.widget.load();
37+
window.HubSpotConversations?.widget.open();
38+
}
39+
};
40+
2641
scriptLoader(document, `//js.hs-scripts.com/${hubspotTrackingId}.js`, { id: 'hs-script-loader' });
2742
window._hsq = window._hsq || [];
2843
window.hsConversationsSettings = {
2944
loadImmediately: loadImmediately,
3045
};
46+
47+
window.hsConversationsOnReady = [...(window.hsConversationsOnReady || []), openFromMetaTag];
3148
};
3249

3350
export const hubspotIdentifyUser = ({

0 commit comments

Comments
 (0)