Skip to content

Commit b924d7e

Browse files
author
Josh Goldberg
authored
fix(tracking): remove navigator.sendBeacon .bind and add try/catch
Simplifies the `navigator.sendBeacon` call to avoid scoping shenanigans, and adds a `try`/`catch` if all else fails.
1 parent bee0994 commit b924d7e

File tree

2 files changed

+25
-5
lines changed

2 files changed

+25
-5
lines changed

packages/tracking/src/events/__tests__/track.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,24 @@ describe('createTracker', () => {
126126
{ body: expect.any(FormData), method: 'POST' }
127127
);
128128
});
129+
130+
it('calls to fetch when beacon throws an error', () => {
131+
Object.defineProperty(navigator, 'sendBeacon', {
132+
writable: true,
133+
value: () => {
134+
throw new Error('Oh no!');
135+
},
136+
});
137+
138+
tracker[event](expectedProps);
139+
140+
expect(
141+
fetch
142+
).toHaveBeenCalledWith(
143+
'https://www.codecademy.com/analytics/user?utm_source=twitter',
144+
{ body: expect.any(FormData), method: 'POST' }
145+
);
146+
});
129147
});
130148
};
131149

packages/tracking/src/events/track.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,16 @@ export const createTracker = ({ apiBaseUrl, verbose }: TrackerOptions) => {
2323
form.append(k, v.toString());
2424
}
2525

26-
// Firefox allows users to disable navigator.sendBeacon, and very old Safari versions don't have it.
27-
const sendBeacon =
26+
try {
27+
// Firefox allows users to disable navigator.sendBeacon, and very old Safari versions don't have it.
2828
// [WEB-1700]: Additionally, Chrome 79-80 gives "Illegal invocation" with ?., so through 2022 we should support them.
2929
// It seems similar to this: https://github.com/vercel/next.js/issues/23856
3030
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
31-
navigator.sendBeacon && navigator.sendBeacon.bind(navigator);
32-
if (sendBeacon?.(uri, form)) {
33-
return;
31+
if (navigator.sendBeacon && navigator.sendBeacon(uri, form)) {
32+
return;
33+
}
34+
} catch {
35+
// Even with the proper scoping, Chrome 79-80 still gives "Illegal invocation" crashes. Sigh.
3436
}
3537

3638
// Either way, we fall back to standard fetch if sendBeacon fails.

0 commit comments

Comments
 (0)