snowplow / snowplow-javascript-tracker

Snowplow event tracker for client-side and server-side JavaScript. Add analytics to your websites, web apps and servers.
http://snowplowanalytics.com
BSD 3-Clause "New" or "Revised" License
543 stars 220 forks source link

Add support for installation via Bower #432

Closed ghost closed 7 years ago

ghost commented 8 years ago

Just had a question about trying to load snowplow through Bower, in which case the sp.js file would be bundled with the application as an installed dependency.

To implement this, I did the following

  1. Removed .gitignore from the dist folder in my fork of snowplow-tracker-javascript
  2. Ran grunt
  3. Committed the generated files
  4. Added this fork as a dependency in bower.json of my application

Essentially, in this case, the build would handle injecting sp.js into a script tag (before any application scripts) in index.html.

This would mean not having to include that part of the setup snippet that creates the script tag and sets the src, essentially now I would only need / want

 (function (p, l, o, w, i) {
      if (!p[i]) {
        p.GlobalSnowplowNamespace = p.GlobalSnowplowNamespace || [];
        p.GlobalSnowplowNamespace.push(i);

        p[i] = function () {
          (p[i].q = p[i].q || []).push(arguments);
        };

        p[i].q = p[i].q || [];
      }
    }(window, document, null, null, 'snowplow'));

When trying this, I no longer see snowplow analytic traffic in Chrome network tab.

Is this possible? Eventually, I would like my build to handle uploading files to S3 / Cloudfront, either as individual files or conact / min file, and this would reduce the coupling between this init script (since it requires specifying a path), and how snowplow gets loaded into my application. We also want to be able to version our fork as we will be modifying it as need to support additional tracking metrics over time, which again help with not having to specify a path in the setup snippet.

Any thoughts / feedback appreciated.

alexanderdean commented 8 years ago

Hi Owen - it's an interesting idea. We haven't done anything with Bower - but if Bower can handle async libraries, then I can't see why it wouldn't work...

ghost commented 8 years ago

Hi @alexanderdean, thanks for the reply!

I guess the emphasis is less on Bower per se, but rather including sp.js in a script tag in an a HTML file rather than explicitly through the "setup" snippet that expects a path to the location of sp.js to be passed into the IIFE, eg.

}(window, document, 'script', '//d111111abcdef8.cloudfront.net/sp.js', 'snowplow'));

Bower just happens to be the tool by which I have chosen to specify that snowplow should be "downloaded" locally so that my application can do something with it.

From there it's up to me how I manage that file so that it can be included via a script tag, using a tool like wiredep, which would add something like this to my index.html <script src="/bower_components/snowplow/dist/sp.js"></script>

I could have just as easily copy / pasted the source into a file in my project without bower.

Is there something specific to the "setup" snippet (which dynamically creates the script tag and appends it to the last script tag) that might cause it not execute analytic events? Maybe something to do with asynchronous loading?

mpolichette commented 8 years ago

NPM support would be awesome also! :)

mcouzinet commented 8 years ago

Support for NPM and Bower would be cool. We just need a compile version of the lib.

remove .gitignore inside build dir ?

alexanderdean commented 8 years ago

Okay, this one seems to be a popular one, scheduling.

Can commenters on this ticket give a more precise explanation of their use case? Loading analytics libraries in an async fashion from CDNs (as we do today) is pretty much the gold standard these days - clearly from this ticket, commenters have another use case in mind - what is it?

mcouzinet commented 8 years ago

For me it's a Cordova project. We embed the tracker.

ghost commented 8 years ago

My use case (I'm the OP) is that we manage dependencies through bower.json as part of our build process, and this includes a fork of this project with some custom tweaks to support our application's needs. Being able to use a Gulp plugin tool like wiredep to automatically template these script files for us is very convenient. As far as CDN hosting, we use S3 / CloudFront, so that covers us there.

So I am looking to use <script> instead of the "init" snippet as posted in my opening comment.

mpolichette commented 8 years ago

My use case is to include the javascript tracker on our app which our customers embed on their own sites. We want to log to our own analytics and we don't want to interfere with any of their sites. Being able to include the tracker via npm import would allow us to bundle and not interact with the global scope.

alexanderdean commented 8 years ago

Makes sense @mpolichette , @obuckley-kenzan , @mcouzinet , thanks for sharing!

rarkins commented 7 years ago

@alexanderdean wrote:

Loading analytics libraries in an async fashion from CDNs (as we do today) is pretty much the gold standard these days

Assuming by "gold standard" we mean the ideal against which others are compared, this is definitely not the case anymore.

Much preferred is to pull third party dependencies via npm as part of a website's frontend build, which gives benefits such as:

Unfortunately, most "SaaS" services including analytics do like you describe - load third party files from CDNs and give no other choice. This also gives them the chance to "move fast and break things" without customers noticing, because if they publish a faulty update they can quickly replace it thanks to rather low expires times on their CDN resources. You notice this if you run something like PageSpeed or WebPagetest and they point out the absurdly low expires of many of these CDN-hosted files.

I prefer the approach used by Mixpanel, who support both the async-loaded CDN scripts as well as "roll your own".

Their javascript tracker npm repository: https://www.npmjs.com/package/mixpanel-browser

Example JS you can build/bundle with client:

var mixpanel = require('mixpanel-browser');

mixpanel.init("YOUR_TOKEN");
mixpanel.track("An event");
rarkins commented 7 years ago

@obuckley-kenzan did you solve your problem from a year ago? i.e. getting snowplow to work without asynchronously loading the library from CDN?

alexanderdean commented 7 years ago

Hi @rarkins - thanks for the detailed case for making the browser-side JavaScript library available as a npm dependency for inclusion as part of the front-end build. You made a compelling argument.

I have:

ghost commented 7 years ago

this is great to hear @alexanderdean !

Would you see the snowplow team also supporting publishing to Bower as well? I understand NPM is extremely popular nowadays for managing / loading client side scripts, but Bower is still in heavy use with some good tooling around it, like wiredeps mentioned above.

Would be interested to hear your thoughts on that. Let me know if I should ask in 541 instead and I am happy to help with getting this into any on of the available JS package managers NPM, Bower, JSPM.

Thanks again for taking a time to review and advance this request!

ghost commented 7 years ago

@rarkins I did not, still using the current solution from my original comment.

alexanderdean commented 7 years ago

Hey @obuckley-kenzan - yes I imagine we will support publishing to Bower, as most of the heavy lifting if I understand correctly will be in #541...

ghost commented 7 years ago

Thanks so much @alexanderdean ! Let me know if I can help!

sandeshputtaraju commented 7 years ago

@obuckley-kenzan i need a help in snowplow configuration.

i am getting below error while running stream enrich. When i run the below command

/home/hadoop/snowplow/2-collectors/scala-stream- collector/target/scala-2.10/snowplow-stream-collector-0.9.0 --config /home/hadoop/snowplow/2-collectors/scala-stream-collect or/target/scala-2.10/collector.conf | ./snowplow-stream-enrich-0.10.0 --config enrich.conf --resolver file:/home/hadoop/snow plow/3-enrich/config/iglu_resolver.json --enrichments file:/home/hadoop/snowplow/3-enrich/config/enrichments

/


> {"line":"151200121ForkJoinPool+2+worker+5ERRORcsscscalastreamScalaCollector+Failurebindingtopors=","errors":[{"level":"error  ","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried to read 2 bytes, but only got 1 bytes  . (This is often indicative of an internal error on the server side. Please check your server logs.)"}],"failure_tstamp":"20  17-07-21T09:42:06.170Z"}
> {"line":"javalangRuntimeExceptionCommandFailedBindActorakka//scala+stream+collector/user/handler+540057214/1721601578080100L  istNonQ==","errors":[{"level":"error","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried t  o read 2 bytes, but only got 1 bytes. (This is often indicative of an internal error on the server side. Please check your s  erver logs.)"}],"failure_tstamp":"2017-07-21T09:42:06.180Z"}
> {"line":"atcomsnowplowanalyticssnowplowcollectorsscalastreamScalaCollectoranonfun3applyScalaCollectorAppscala118snowplow+str  eam+collector+090090=","errors":[{"level":"error","message":"Error deserializing raw event: Cannot read. Remote side has clo  sed. Tried to read 1 bytes, but only got 0 bytes. (This is often indicative of an internal error on the server side. Please   check your server logs.)"}],"failure_tstamp":"2017-07-21T09:42:06.181Z"}
> {"line":"atcomsnowplowanalyticssnowplowcollectorsscalastreamScalaCollectoranonfun3applyScalaCollectorAppscala116snowplow+str  eam+collector+090090=","errors":[{"level":"error","message":"Error deserializing raw event: Cannot read. Remote side has clo  sed. Tried to read 1 bytes, but only got 0 bytes. (This is often indicative of an internal error on the server side. Please   check your server logs.)"}],"failure_tstamp":"2017-07-21T09:42:06.181Z"}
> {"line":"atscalaconcurrentFutureanonfunflatMap1applyFuturescala251snowplow+stream+collector+09009","errors":[{"level":"error  ","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried to read 1 bytes, but only got 0 bytes  . (This is often indicative of an internal error on the server side. Please check your server logs.)"}],"failure_tstamp":"20  17-07-21T09:42:06.182Z"}
> {"line":"atscalaconcurrentFutureanonfunflatMap1applyFuturescala249snowplow+stream+collector+09009","errors":[{"level":"error  ","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried to read 1 bytes, but only got 0 bytes  . (This is often indicative of an internal error on the server side. Please check your server logs.)"}],"failure_tstamp":"20  17-07-21T09:42:06.182Z"}
> {"line":"atscalaconcurrentimplCallbackRunnablerunPromisescala32snowplow+stream+collector+09009w==","errors":[{"level":"error  ","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried to read 2 bytes, but only got 0 bytes  . (This is often indicative of an internal error on the server side. Please check your server logs.)"}],"failure_tstamp":"20  17-07-21T09:42:06.182Z"}
> {"line":"atscalaconcurrentimplExecutionContextImplanon3execExecutionContextImplscala107snowplow+stream+collector+09009w==","  errors":[{"level":"error","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried to read 2 byt  es, but only got 0 bytes. (This is often indicative of an internal error on the server side. Please check your server logs.)  "}],"failure_tstamp":"2017-07-21T09:42:06.183Z"}
> {"line":"atscalaconcurrentforkjoinForkJoinTaskdoExecForkJoinTaskjava260snowplow+stream+collector+09009w==","errors":[{"level  ":"error","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried to read 2 bytes, but only got   0 bytes. (This is often indicative of an internal error on the server side. Please check your server logs.)"}],"failure_tst  amp":"2017-07-21T09:42:06.183Z"}
> {"line":"atscalaconcurrentforkjoinForkJoinPoolWorkQueuerunTaskForkJoinPooljava1339snowplow+stream+collector+09009","errors":  [{"level":"error","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried to read 1 bytes, but   only got 0 bytes. (This is often indicative of an internal error on the server side. Please check your server logs.)"}],"fai  lure_tstamp":"2017-07-21T09:42:06.184Z"}
> {"line":"atscalaconcurrentforkjoinForkJoinPoolrunWorkerForkJoinPooljava1979snowplow+stream+collector+09009w==","errors":[{"l  evel":"error","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried to read 2 bytes, but only   got 0 bytes. (This is often indicative of an internal error on the server side. Please check your server logs.)"}],"failure  _tstamp":"2017-07-21T09:42:06.184Z"}
> {"line":"atscalaconcurrentforkjoinForkJoinWorkerThreadrunForkJoinWorkerThreadjava107snowplow+stream+collector+090090=","erro  rs":[{"level":"error","message":"Error deserializing raw event: Cannot read. Remote side has closed. Tried to read 2 bytes,   but only got 1 bytes. (This is often indicative of an internal error on the server side. Please check your server logs.)"}],  "failure_tstamp":"2017-07-21T09:42:06.184Z"}
> 

Please help me out to overcome this error

chuwy commented 7 years ago

Hi @sandeshputtaraju,

Please direct your questions to our community forums. This project's bugtracker is for issues and feature requests for JS Tracker (not Scala Collector) only.

alexanderdean commented 7 years ago

Hi @sandeshputtaraju - this is your final warning. If you continue to spam our community, you will be blocked on all channels.

thescientist13 commented 7 years ago

@alexanderdean Just an update on this (and maybe to see if there's anything I could do to help).

Bower is in maintenance mode only now, and the "modern" option is to publish to and install from the NPM registry (using npm-cli, Yarn, etc). I don't think it changes the implementation details of this issue all that much, but just thought maybe it could better help direct / focus the effort.

Let me know your thought! (fyi - I was the OP, I no longer use that GitHub account)

alexanderdean commented 7 years ago

Thanks @thescientist13 - that makes sense. We'll reboot this ticket then when this release gets scheduled. Cheers for checking in!

danny-andrews commented 7 years ago

Maybe this ticket should be closed in favor of https://github.com/snowplow/snowplow-javascript-tracker/issues/541 since bower is deprecated in favor of npm.

alexanderdean commented 7 years ago

Hi @danny-andrews - that's probably a good idea, closing...

alexanderdean commented 6 years ago

cc @mhadam as this might be interesting