-
Notifications
You must be signed in to change notification settings - Fork 6
feat(umami-plugin): inject mock on umami script download error #313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
emizzle
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for doing this Jules.
Regarding testing, I'd recommend figuring out a way to test this prior to merging. The easiest way would be to remove the window.umami object before the test runs.
One other important note, we removed the button from the codex website that has this umami tracking script, however it is easily testable (manually) in a brave browser.
| s.onerror = onError; | ||
| (document.head || document.getElementsByTagName('head')[0]).appendChild(s); | ||
| })();` | ||
| return { headTags: [{ tagName: 'script', innerHTML: loader }] } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a very strange way to add a head tag honestly. If I understand this correctly, it adds a head tag that then adds another head tag that had the onerror attribute set. I'm assuming you tried adding the onerror attribute first, eg
const attributes = {
defer: true,
src: scriptSrc,
'data-website-id': websiteId,
onerror: function onError() {
if(!window.umami){
console.warn('[docusaurus-plugin-umami] Failed to load Umami script - using mock tracker instead.');
window.umami = {
track: function(){},
identify: function(){}
}
}
}
}Another option, according to the plugin docs, is to return a scripts object, eg
return {
scripts: [
{
src: scriptSrc,
defer: true,
'data-website-id': websiteId,
onerror: function onError() {
if(!window.umami){
console.warn('[docusaurus-plugin-umami] Failed to load Umami script - using mock tracker instead.');
window.umami = {
track: function(){},
identify: function(){}
}
}
}
},
],
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes the implementation is a bit "complex" because there was no other way to be able to inject the mock when the client throws an error when downloading the tracking script from umami.
-
Approach 1: It won’t work because functions in attributes are serialized as strings by docusaurus, so the
onerrorhandler never actually runs. It will give something like"[object Function]". -
Approach 2: It won’t work either because returning a
scriptsarray isn’t part of the docusaurus plugin API, plugins must inject scripts viainjectHtmlTags().
The docs you linked are the one fordocusaurus.config.jsto, among other things, import and configure external plugins. For the docs related to creating a plugin, you can refer to this doc for the available methods in a plugin and this one for the details regardinginjectHtmlTags()
|
@emizzle thanks for your review 🙏 As I've said here, there was really no other way to inject the mock upon triggering an error via the head tag. However when scrolling the docs I realized that we could use client modules instead to have a cleaner implementation than the "complex" one I had to previously do. So I've refactored the code into something more digest and simple using client modules. Please tell me what you think - no need for
As I've said on the description of the PR, I already found a way to test locally. Since I use Brave browser and it is the browser triggering the error it's quite straightforward:
|
|
THanks Jules, this is much cleaner.
Apologies for the misunderstanding. What I meant was that it would be prudent to figure out an automated way of testing this, eg with a unit test. A unit test would allow this to be confirmed in other environments (eg CI) and it prevents future regressions. |
Fixes the error raised here acid-info/codex.storage#59 (comment)
After taking more time to review it, the problem is actually that when the umami script is blocked from being downloaded by the client, we get an
umami undefinederror afterwards when trying to invoque the track function from it.So the problem is not that we allow the script to be downloaded on other domains than the one specified in the
dataDomainsproperty (c.f. acid-info/codex.storage#59 (comment)). If the script is downloaded on any other domains than the one.s specified, nothing will be tracked and no error will ever be triggered as the umami object will be correctly defined. So all good.So my approach was to inject the mock umami object, as suggested by @emizzle, only when downloading the script gets blocked by the client thus triggering an error.
The mock contains two functions,
trackandidentify; the code here from Umami's repo shows that track should be enough, but the Umami docs here mention anidentifyfunction, so to play it safe I added both.Next step after merge:
codex.storage(I tested locally before ofc)@acid-info/docusaurus-umamipackage's version.