GithubHelp home page GithubHelp logo

simpleanalytics / scripts Goto Github PK

View Code? Open in Web Editor NEW
82.0 4.0 13.0 6.11 MB

Open Source Public Scripts for Simple Analytics

Home Page: https://www.simpleanalytics.com

License: MIT License

JavaScript 79.25% Shell 5.88% HTML 14.87%
analytics no-cookies privacy privacy-tools analytics-tracking analyticsjs google-analytics

scripts's Introduction

Simple Analytics logo

Scripts

Simple Analytics is a privacy-first analytics tool with a strong mission: never invade the privacy of your visitors. We just show you the essentials: page views, referrers, top pages, and devices. We don't use cookies. We don't collect any personal data. So no cookie banners or GDPR to worry about. When a service is free you are the product. We won't ever sell your data. As a result, we require a subscription.

Open Source

As our public scripts are very important in our mission to privacy we decided to make the source code available. We use the MIT license which is short and to the point. It lets you do almost anything you want with this project, like making and distributing closed-source versions. See LICENSE for more info.

Contribute

If you want to contribute, you probabaly want to contribute to our /src/default.js or /src/auto-events.js files. These files compile into a few versions of our script by compile.js. They end up on our CDN, custom domains, and the Cloudflare app.

In default.js you see some weird syntax in the comments. For example, /** if ignorepages **/ [some code] /** endif **/. These comments are converted to handlebars like this: {{#if ignorepages }} [some code] {{/if}}. In this case, ignorepages is a variable used in minify.js that takes care of what functionality to show in what script. Our main script is the latest.js script which includes all features. We also have a light.js script that obviously doesn't.

If you contribute, make sure to use npm run build, copy the script to a website, and check if it works correctly.

Run this locally

Just run npm run watch and every file will be validated and compiled on save. We minify our scripts with UglifyJS, a well-known JavaScript minifier.

The most important file of the repository is /src/default.js

Device testing is sponsored by BrowserStack

We run our public script with more than 50 browsers on many different (real) devices. We support Internet Explorer 9 (not sure who is still using that) and up. Including many mobile browsers and less common devices. We get amazing sponsorship from BrowserStack. Thanks, BrowserStack!

BrowserStack Logo

Contact

Feel free to drop any issues you have with our open-source scripts. If you want to contact us you can also use our contact form or email listed here: simpleanalytics.com/contact.

scripts's People

Contributors

adriaandotcom avatar dependabot[bot] avatar jibsaramnim avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

scripts's Issues

Fix missing source map for version 8

When retrieving the following Simple Analytics file via my custom CNAME:
https://sa.example.com/v8/app.js

This file has an embedded "sourceMappingURL" set to "v8.js.map", which does not exist. It seems like this should point to "app.js.map", which does exist. Currently this results in a console warning.

Use document.currentScript to get the current running script

Instead of using this:

scripts/src/default.js

Lines 287 to 288 in 3b270ce

// Find the script element where options can be set on
var scriptElement = doc.querySelector('script[src*="' + baseUrl + '"]');

We can use:

var scriptElement = doc.currentScript || doc.querySelector('script[src*="' + baseUrl + '"]');
  • We can now support multiple scripts on one page with multiple settings

Tasks

Make localhost detection optional

Sometimes you don't want to skip the Simple Analytics on local scripts. For example with Chrome extensions.

I am currently trying to collect some usage information about a chrome extension using SimpleAnalytics - is that possible?
I want to track some events in the extension popup-window (that appears when clicking the extension icon in the top right). This extension popup is hosted by Chrome on "chrome-extension://[Random extension ID]/popup.html" so I used the "data-hostname" argument to set the hostname to another custom URL that I created for this extension.

Using this technique, Simple Analytics is still logging "Simple Analytics: Not sending request from [Random extension ID here]". It looks like the random extension ID is triggering the localhost detection as "locationHostname.indexOf(".") == -1" will eval to true. Is there a way to disable this check or any other recommendations when using for extensions?

scripts/src/default.js

Lines 367 to 374 in 3b270ce

/** unless testing **/
// Don't track when localhost or when it's an IP address
if (
locationHostname.indexOf(".") == -1 ||
/^[0-9]+$/.test(locationHostname.replace(/\./g, ""))
)
return warn(notSending + "from " + locationHostname);
/** endunless **/

Let's make this optional via data-force=true, data-force-run=true, or data-always-run=true. Force makes the most sense to me because we then also can bypass the check if the script is loaded twice. Maybe some people want to load our script multiple times.

Illegal invocation with sendBeacon and URL has an error

From a very helpful customer, we got this error report:

The following is logged to console:
Simple Analytics: Uncaught TypeError: Illegal invocation
At this stage, it seems exclusively happening on Chrome/Windows.

Good read: https://xgwang.me/posts/you-may-not-know-beacon/

It does suggest that if a URL has an error, sendBeacon will throw "TypeError: Illegal invocation".

This also seemed to effect the next.js project as well: vercel/next.js#23856 (fix: https://github.com/vercel/next.js/pull/26601/files)

Use window.addEventListener instead of window.onhashchange

In the following line, it would be nicer to use window.addEventListener('hashchange', hashHandler, false); instead of window.onhashchange = hashHandler, because it plays nicer with other code:

window.onhashchange = function() {

It just took me way longer than I care to admit to debug an issue caused by this, which only occurred in production, since my dev-builds don't use the analytics script.

Add click event handler if onclick is set

We use onClick when somebody clicks a link. We only set this when there is no onClick handler set. But for some frameworks like Next.js all links have onClick events.

scripts/src/auto-events.js

Lines 149 to 185 in ed9efd1

if (!link.getAttribute("onclick")) {
// Collect download clicks
if (
optionsLink.downloads &&
/^https?:\/\//i.test(link.href) &&
new RegExp(
".(" + (optionsLink.downloadsExtensions || []).join("|") + ")",
"i"
).test(link.pathname)
) {
collect = "download";
// Collect outbound links clicks
} else if (
optionsLink.outbound &&
/^https?:\/\//i.test(link.href) &&
link.hostname !== window.location.hostname
) {
collect = "outbound";
// Collect email clicks
} else if (optionsLink.emails && /^mailto:/i.test(link.href)) {
collect = "email";
}
if (collect) {
var onClickAttribute = "saAutomatedLink(this, '" + collect + "');";
if (
!link.hasAttribute("target") ||
link.getAttribute("target") === "_self"
)
onClickAttribute += " return false;";
link.setAttribute("onclick", onClickAttribute);
}
}

To not overwrite that behavior we can attach an additional event that does not wait for our request to be done:

if (!link.getAttribute("onclick")) {
  // current code
} else {
  // new code
  link.on('click', function() {
    // current code
  })
}

Why not always use the second method? Well, we want to wait for the event to be sent to our server before sending the user to the next page. So it's a backup method.

Scrolled bug

Hi there,

I Was looking at your code and saw that:

scrolled = window.setTimeout(position, 500);

scrolled = window.setTimeout(position, 500);

setTimeout returns a TimeoutID, that we can pass to clearTimeoutto cancel the future call. So it won't do what you think.

You may want to do:

window.setTimeout(function () {
  scrolled = position()
}, 500);

Anyway, great product!

Event constructor not supported in Internet Explorer 11 and below

Hello,

The constructor new Event() is not supported in Internet Explorer, and this is causing scripts to break when they use history.pushState(). It looks like you are checking that Event is defined before trying to use the constructor, but Event is defined in IE, just not as a function.

There are a couple of possible solutions that come to mind: polyfilling or substituting the constructor somehow, or checking not just that Event is defined, but that it is defined as a function.

Thanks,

Jonathan Sutcliffe

Send session id with page views as well

We send a session id with events, but it makes sense to send it with page views as well.

That way we can link events (that happen on one page or multiple in a SPA) to a page view.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.