-
Notifications
You must be signed in to change notification settings - Fork 133
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
feat: add sendBeacon support #412
Conversation
- add transport as option (either http or beacon) - support sending event with either transport mechanism
Updated the confluence doc on sendBeacon to describe what I'm going for with this PR: https://amplitude.atlassian.net/wiki/spaces/sdk/pages/1492058287/Beacon+API+-+JS+SDK+Proposal#Implementation%3A |
This pull request introduces 28 alerts when merging 7902a98 into 564f656 - view on LGTM.com new alerts:
|
src/amplitude-client.js
Outdated
@@ -1633,6 +1688,23 @@ AmplitudeClient.prototype.sendEvents = function sendEvents() { | |||
checksum: md5(Constants.API_VERSION + this.options.apiKey + events + uploadTime), | |||
}; | |||
|
|||
if (!navigator.sendBeacon) { |
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.
hm, I think I would expect this in the validateTransport
function and not in sendEvents
const handleVisibilityChange = () => { | ||
const prevTransport = this.options.transport; | ||
this.setTransport(Constants.TRANSPORT_BEACON); | ||
onExitPage(); |
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.
thoughts on hooking the current object with onExitPage(this)
allowing users to access the client earlier?
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.
As in, so they can write the callback on a line before initializing the client with it? The way I was testing it, as long as the amplitude object is in scope within the file, it doesn't need to be initialized until onExitPage is called. So the following is fine:
const onExitPage = () => {
amplitude.getInstance().logEvent('logging onExitPage');
};
amplitude.getInstance().init('API_KEY', userID, { onExitPage });
But if there's another benefit you're thinking of by making the client an argument, it would be an easy change to make
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.
It might make it easier for people using the snippet to use the full client obj (incl. "private" methods and the full list of options post-init to construct event properties) but you are right that everything publicly supported is available.
I don't feel too strongly about this though so we can not do this and see what people actually want as arguments to this option!
this.options.transport = Constants.TRANSPORT_HTTP; | ||
} | ||
|
||
if (this.options.transport === Constants.TRANSPORT_BEACON) { |
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.
might be too much, but would be good to replace a lot of these with a small descriptive helper function like doesTransportSupportSaveEvents
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.
I tried adding helper functions, but since there are only two transports now, they didn't add much descriptivity compared to checking the value itself. If there end up being more than two, then definitely there should be helper functions to categorize them like this
@@ -108,6 +108,18 @@ const validateDeviceId = function validateDeviceId(deviceId) { | |||
return true; | |||
}; | |||
|
|||
const validateTransport = function validateTransport(transport) { |
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.
is this checked on initialization? In case it comes in bad
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.
it's not but it should be, good call
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.
Not super familiar with our build system as of now, but why is this PR adding 2 5k sized files?
@kelvin-lu those files were built while I was testing this PR locally and weren't in the gitignore, so I accidentally committed them. I just now took them out of the PR and added them to the gitignore |
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.
overall lgtm!
I think the only other thing DX wise is some sort of warning that the Transport Beacon does not retry like regular XHR requests. I feel like that might be a source of questions/data governance concerns
src/amplitude-client.js
Outdated
return this._q.push(['setTransport'].concat(Array.prototype.slice.call(arguments, 0))); | ||
} | ||
|
||
const t = transport.toLowerCase(); |
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.
not sure how to manage this in validateTransport
but you should probably check that this is a string before using toLowerCase
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.
perhaps like validateProperties
we coudl have validateTransport
return a sanitary version of the string? :)
That's an interesting point RE DX. I have a followup ticket to update the dev docs with instructions for sendBeacon, so I'll definitely mention the lack of retry. |
I'll tighten up |
Summary
Checklist