exokitxr / exokit

Native VR/AR/XR engine for JavaScript 🦖
MIT License
994 stars 117 forks source link

exokit DOM doesn't support google analytics #1230

Open shawwn opened 5 years ago

shawwn commented 5 years ago

Describe the bug What happened, and what did you expect to happen?

I created a basic index.html with google analytics, then deployed it using now. When I visit the resulting url in chrome, I see the visit in my google analytics page.

When you go to the page using exokit, the google analytics javascript executes (e.g. ga is defined globally, as expected). However, on the google analytics dashboard, nothing happens. (It should show that a user visited the site.)

The root problem is that exokit's fetch function doesn't send Cookie: ${document.cookie} in the request.

You can prove this by making an html page with google analytics, copying the collect?v... request as fetch, then pasting the resulting fetch into exokit's CLI. Google analytics won't see anything. If you add 'headers: { 'Cookie': document.cookie }` to the fetch options, everything works fine.

One fix is for window-fetch to check whether typeof document !== 'undefined', and if so, set 'Cookie': document.cookie in the headers. What do you think the best way to fix this would be?

document.cookie should probably be saved to some kind of persistent storage, too (if it isn't already).

avaer commented 5 years ago

This would be more broadly, cookie support.

I don't think window-fetch should be aware of document -- instead we should follow the cookie spec and tell window-fetch (and window-xhr) to inject cookies when needed, from the DOM.

shawwn commented 5 years ago

Actually...

It has nothing to do with document.cookie.

When I set cookie: ... in the headers: field, I also set 'user-agent': 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'.

The fetch worked, and I erroneously assumed it was due to sending document.cookie. But in fact, it was the user agent.

To be clear, if I right click -> copy as fetch, I get this:

fetch("https://www.google-analytics.com/r/collect?v=1&_v=j77&a=1162872587&t=pageview&_s=1&dl=https%3A%2F%2Fga-ixedatnjya.now.sh%2F&ul=en-us&de=UTF-8&sd=24-bit&sr=1440x900&vp=642x771&je=0&_u=AACAAUAB~&jid=1606228715&gjid=2106366670&cid=1386529399.1561548967&tid=UA-142794820-1&_gid=814084279.1561548967&_r=1&gtm=2ou6c0&z=371849690", {"credentials":"omit","referrer":"https://ga-ixedatnjya.now.sh/","referrerPolicy":"no-referrer-when-downgrade","body":null,"method":"GET","mode":"cors"});

pasting that into exokit's CLI doesn't work. But if you add

headers: {'user-agent': 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}, 

to the fetch options, then it works. The final working fetch is:

fetch("https://www.google-analytics.com/r/collect?v=1&_v=j77&a=1162872587&t=pageview&_s=1&dl=https%3A%2F%2Fga-ixedatnjya.now.sh%2F&ul=en-us&de=UTF-8&sd=24-bit&sr=1440x900&vp=642x771&je=0&_u=AACAAUAB~&jid=1606228715&gjid=2106366670&cid=1386529399.1561548967&tid=UA-142794820-1&_gid=814084279.1561548967&_r=1&gtm=2ou6c0&z=371849690", {headers: {'user-agent': 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}, "credentials":"omit","referrer":"https://ga-ixedatnjya.now.sh/","referrerPolicy":"no-referrer-when-downgrade","body":null,"method":"GET","mode":"cors"});

whenever I paste that into exokit's CLI, google analytics sees it.

I'm not sure why. But after checking and re-checking, I'm pretty confident this issue is solely due to the user agent setting.

avaer commented 5 years ago

We do indeed use an Exokit-specific user agent. Does that mean that this issue is resolved?

shawwn commented 5 years ago

No, I don't think so. If you grep the codebase for fetch(..., you'll notice src/DOM.js doesn't actually pass in exokit's useragent as a fetch parameter.

It's using the default value of the window-fetch package, which is apparently node-fetch/1.0 (+https://github.com/bitinn/node-fetch)

shawwn commented 5 years ago

I can confirm that changing every fetch(foo) to fetch(foo, {headers: {'user-agent': `User-Agent: ${this.ownerDocument.implementation._window.navigator.userAgent}`}}) in src/DOM.js fixes this issue.

Is there a better way to access window.navigator.userAgent for the current HTML element? Especially given the new user-parallel work.

shawwn commented 5 years ago

https://stackoverflow.com/questions/16010204/get-reference-of-window-object-from-a-dom-element seems to work:

 i=document.createElement('img');
document.body.appendChild(i);
doc=i.ownerDocument;
doc.defaultView || doc.parentWindow;
avaer commented 5 years ago

Thanks for the investigation here.

It sounds like the forward-compatible way to handle this case would be to finish the intercept support and perform that interception to set the User-Agent header.