DavidWells / analytics

Lightweight analytics abstraction layer for tracking page views, custom events, & identifying visitors
https://getanalytics.io
MIT License
2.43k stars 247 forks source link

Analytics behind a proxy #146

Open samermurad opened 3 years ago

samermurad commented 3 years ago

Let me start by thanking you for this wonderful lib, I already use it in a couple of projects in our company. Last week a new situation has a-raised, where we have an electron app, which needs to run behind a proxy. Now the problem is, that the infra of the app is built in such a way that the requests go out from the main process of electron, so basically a nodeJs context (and not a browser) so proxy configs are not there by default. For our REST Api, I needed to add an extra logic that resolves the proxy settings of the machine using the web Session of the chromium browser.

Bottom line, I need to do the same thing with the analytics module in order for the requests to go through the proxy (all other traffic will be blocked)

Is it somehow possible to tinker with the networking module of the lib? if so can you direct me in the right direction? If I'll end up having a good solution, I'll open a PR request with the changes for future needs of other devs:)

DavidWells commented 3 years ago

You can have a plugin send data anywhere you wish 😃

See https://github.com/DavidWells/analytics#community-plugins & https://www.npmjs.com/package/@standardorg/analytics-fetch it's a tiny plugin to send data to your own backend. In your case, this would be to a google analytics proxy.

If GA is running in the client of your electron app, you can use the customScriptSrc option https://getanalytics.io/plugins/google-analytics/#custom-proxy-endpoint to load a customize GA script that posts to your proxy endpoint. More details on that here https://www.freecodecamp.org/news/save-your-analytics-from-content-blockers-7ee08c6ec7ee/

samermurad commented 3 years ago

Hey man, thank you for the quick response, your message sent me on a bit of a research, so my problem is that we don't want the analytics to come through our servers (for various reasons), and we need the main process of the electron app to tunnel ALL outgoing requests through an optional existing proxy on the system settings, we are building an app for corporates, so often employees need to be connected to an office cable of some sort, so all everything must be tunneled, otherwise everything is blocked.

I tried to tinker with both your @analytics/google-analytics and the universal-analytics package, and I have reached some results

This is kind of a long story, I hope you'll bare with me here, I'll try to break it down in an orderly manner, yes, there is a bottom line for it.

The universal-analytics already supports requestOptions, and passes them to the request package before executing requests, so technically, configuring a correct Http(s) Agent for proxy tunneling and setting it on the universal-analytics client object, actually builds a correct request. This however has two problems:

  1. your lib has currently no current way to get the installed plugins (unless im missing something?), so I needed to save the plugins on a new key after the initializations code, something like:
const plgns = createPlugins(trackers);
const analytics = Analytics({
  debug: true,
  app: Env.brand,
  plugins: plgns,
});
(analytics as any).pluginsObjects = plgns;

then I tinkered the universal-analytics to return the client object on the initialization code, enabling me to set analytics.pluginsObjects[n].client.options.requestionOptions and to load the Agent on it. (yes this is very ugly)

  1. but universal-analytics uses the request lib, which is deprecated, and should not be used, there where a couple of attempts by the maintainers to update it, but they reverted that change.

  2. Another problem is with the request lib, is that for an unknown reason, the proxy setting didn't work on windows (I tested on 10 running with parallels)

So this forced my hands "re-write" both the @analytics/google-analytics plugin and the universal-analytics lib, in order to replace the request package as well, I realize this is not Ideal, but it is the quickest option I have for now.

Now why am I ever writing this scroll? the universal-analytics is really not that big, and the request model is only being used for a very simple post request, it's not very complicated task to write that with http/fetch depending on the running env. And IMO, it's a valid point to check whether it's worth it to use the universal-analytics or just update the @analytics/google-analytics package directly communicate with GA.

Before breaking stuff and submitting PRs, I wanted to ask you how you would feel about such a change, If you are interested, I could try to submit such a PR soon (I'll need to make free time, but Im more than willing to do so), where I would simply just completely drop universal-analytics and re-implement the tracking with native modules, allowing for various networking options, And maybe a way to update these options in runtime through Analytics package (?)

I hope this is clear enough, Please let me know something needs clarifying and let me know what you think:).

Again, thank you for a very useful library