Skip to content
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

Rollup strict mode causing errors when CSP is enabled (eg. WebExtensions) #72

Closed
wachunei opened this issue Aug 5, 2020 · 10 comments
Closed
Labels
help wanted Extra attention is needed

Comments

@wachunei
Copy link
Contributor

wachunei commented Aug 5, 2020

When trying to use analytics in a WebExtension there is a strict mode error when bundling.

In the chrome extensions documentation there is a guide to integrate analytics into the extension, they mention that given the tight Content Security Policies, loading the analytics from google requires to explicitly allow it in the manifest by setting:

{
  ...,
  "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'",
  ...
}

Parenthesis: Digging into the code of google analytics plugin I figured out the script is loaded from a different url (https://www.google-analytics.com/analytics.js). My suggestion is to explicitly mention this in the docs.

But just by importing analytics into my main file I get this error:

Screen Shot 2020-08-05 at 18 45 27

I thought it was the url but if looked it up I got this:
Screen Shot 2020-08-05 at 18 46 11

So trying to solve it without having to allow 'unsafe-eval' in the CSP I found this similar issue in other repo: indico/react-overridable#2

What they did to solve it is to disable strict in their rollup config.

I have my extension code pushed in a branch if you want to test this.
Thank you!

(ps: for now I'm going to add unsafe eval 😅)

@DavidWells
Copy link
Owner

Thanks for reporting this. It's an interesting conundrum 😃

Similar reports over here mozilla/pdf.js#11036. This might have been fixed upstream in newer babel versions

Any ideas on how to fix this?

@DavidWells DavidWells added the help wanted Extra attention is needed label Aug 7, 2020
@wachunei
Copy link
Contributor Author

wachunei commented Aug 7, 2020

Here they solved it by configuring rollup to not use strict mode https://github.com/indico/react-overridable/pull/3/files#diff-ff6e5f22a9c7e66987b19c0199636480R15

I certainly don't know if this is the right thing to do.

@wachunei
Copy link
Contributor Author

It seems like analytics + google analytics plugin does not work at all in web extensions.

@wachunei
Copy link
Contributor Author

I've inspected the state in a local dev env and it is correctly tracking events and pageviews:
image

But none of these events/pageviews are showing up in my analytics dashboard, not even from the development environment.

@DavidWells
Copy link
Owner

DavidWells commented Aug 24, 2020

I'm not sure how browser extensions work with analytics.

It's possible that the GA script isn't being loaded into the page b/c the extension doesn't have access to inject GA into the page. This code loads GA into the current page https://github.com/DavidWells/analytics/blob/master/packages/analytics-plugin-google-analytics/src/browser.js#L66-L71

To verify this, override the page call like this:

import Analytics from 'analytics'
import googleAnalytics from '@analytics/google-analytics'

const analytics = Analytics({
  app: 'awesome-app',
  plugins: [
    Object.assign({}, googleAnalytics({
      trackingId: 'UA-1234567'
    }), {
      // Temporary override of the default page call to verify GA is loaded
      page: ({ payload }) => {
        console.log('Testing GA page', payload)
        console.log('Does GA exist?', window.ga)
      }
    }
  ]
})

/* Track a page view */
analytics.page()

If you see "Testing GA page", that means the page call is working. But it might not be hitting a because it exits early if GA doesn't exist on the page https://github.com/DavidWells/analytics/blob/master/packages/analytics-plugin-google-analytics/src/browser.js#L141

Verify that window.ga exists in the chrome extension context.

If it doesn't... You may need to send data to a different backend like in this example https://github.com/netlify-labs/functions-site/blob/master/src/analytics.js#L14-L40. This would send to a backend, then in that backend you can ship data off the google analytics.

@wachunei
Copy link
Contributor Author

The page call is working and the window.ga function is already loaded.

Screen Shot 2020-08-25 at 10 47 08

Trying to debug this I hooked up a track call to a en element click in the options page.

Code:
function OptionsPage() {
  const { page, track } = useAnalytics();

  useEffect(() => {
    page();
  }, []);

  const handleBrandClick = useCallback(() => track("brandclick"), []);

  return (
    <>
      <GlobalStyle />
      <OptionsStyle />
      <Section>
        <Brand width="120" onClick={handleBrandClick} />
      </Section>
      <Section>
        <Title>Usuario</Title>
        <UserForm />
      </Section>
      <Section>
        <Title>Opciones</Title>
        <Options />
      </Section>
      <Section>
        <Title>Servicios</Title>
        <Services />
      </Section>
    </>
  );
}

Should I see some network activity when clicking? Because the only network activity showing up is the script being loaded from https://www.google-analytics.com/analytics.js.

Thanks a lot for your help!

just in case you want to see it yourself you can install the extension and inspect background page or options page (chrome/opera/others, edge, firefox)

@DavidWells
Copy link
Owner

DavidWells commented Aug 27, 2020

Just had a lightbulb moment on this one.

Looking at the protocol it's chrome-extension://. By default google analytics blocks anything that is not https://

Can you add these settings to enable the chrome extension protocol (checkProtocolTask)

import Analytics from 'analytics'
import googleAnalytics from '@analytics/google-analytics'

/* initialize analytics and load plugins */
const analytics = Analytics({
  app: 'my-app',
  plugins: [
    googleAnalytics({
      trackingId: '123-xyz',
      // Override or disable GA Tasks https://bit.ly/31Xetmg
      tasks: {
        // Set checkProtocolTask for electron apps & chrome extensions
        checkProtocolTask: null,
      }
    }),
  ]
})

After you do this, it should* pass data into GA

@wachunei
Copy link
Contributor Author

yaaaay, it works! Thanks David!

@DavidWells
Copy link
Owner

Wooohoo! I will add this to the docs.

I knew it was something funky.

@wachunei
Copy link
Contributor Author

Hey David, after a few days I've been able to capture data from Chrome, Edge and Opera but not Firefox.

My guess is that Firefox disables this by default, but I've enabled/disabled protection rules and nothing happens. Is there any other task you think might be causing this?

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants