Giter VIP home page Giter VIP logo

ackee-tracker's Introduction

ackee-tracker logo

ackee-tracker

Donate via PayPal

A script that interacts with the API of Ackee. Should be included on your site to track data.


Ackee tracker code

🚀 Installation

We recommend loading ackee-tracker from your Ackee instance. This ensures that the script is always in sync with your installation. The script is served as tracker.js or as a name of your choice.

<script async src="https://ackee.example.com/tracker.js" data-ackee-server="https://ackee.example.com" data-ackee-domain-id="hd11f820-68a1-11e6-8047-79c0c2d9bce0"></script>

It's also possible to install ackee-tracker as a module via npm or yarn.

npm install ackee-tracker
yarn add ackee-tracker

🤗 Usage

Type Usage Best for Records (Views) Actions (Events)
Automatically Via script tag Simple sites ⛔️
Manually Via script tag and code Advanced sites
Programmatic Via module Modern sites with build tools

Automatically

The easiest way to send data to your Ackee server is by including the script along with the required attributes. Ackee will now track each page visit automatically.

This approach is perfect for static sites. It tracks a visit whenever a user visits the site or navigates to a new page. Websites with client-side routing however should consider to use any of the other approaches as this one would only track the initial page.

<script async src="dist/ackee-tracker.min.js" data-ackee-server="https://ackee.example.com" data-ackee-domain-id="hd11f820-68a1-11e6-8047-79c0c2d9bce0"></script>

It's also possible to customize Ackee using the data-ackee-opts attribute.

<script async src="dist/ackee-tracker.min.js" data-ackee-server="https://ackee.example.com" data-ackee-domain-id="hd11f820-68a1-11e6-8047-79c0c2d9bce0" data-ackee-opts='{ "ignoreLocalhost": true }'></script>

Manually

Include the JS-file at the end of your body and start tracking page visits by calling create manually.

This approach is perfect for sites without a build system. It gives you more control than the automatic solution, but still allows you to use ackee-tracker without a package manager or JS bundler.

<script src="dist/ackee-tracker.min.js"></script>

<script>
	ackeeTracker.create('https://ackee.example.com').record('hd11f820-68a1-11e6-8047-79c0c2d9bce0')
</script>

Programmatic

Use ackee-tracker as a module and start tracking page visits by calling create.

This approach is perfect if your site uses client-side routing or changes content without reloading the site. It allows you to call Ackee whenever you need.

Example:

const ackeeTracker = require('ackee-tracker')

ackeeTracker.create('https://ackee.example.com').record('hd11f820-68a1-11e6-8047-79c0c2d9bce0')
import * as ackeeTracker from 'ackee-tracker'

ackeeTracker.create('https://ackee.example.com').record('hd11f820-68a1-11e6-8047-79c0c2d9bce0')

⚙️ API

.detect()

Looks for an element with Ackee attributes, creates an instance and starts tracking.

This function runs automatically in a browser environment and fails silently when it can't find a suitable element. You usually don't need to call this function.

Example:

<div hidden data-ackee-server="https://ackee.example.com" data-ackee-domain-id="hd11f820-68a1-11e6-8047-79c0c2d9bce0"></div>
ackeeTracker.detect()

.create(server, options)

Creates a new ackee-tracker instance.

Be sure to assign your instance to a variable. Tracking a visit or event is only possible with an instance.

Examples:

const instance = ackeeTracker.create('https://ackee.example.com')
const instance = ackeeTracker.create('https://ackee.example.com', {
	detailed: false,
	ignoreLocalhost: true
})

Parameters:

  • server {String} An URL that points to your Ackee installation. The server property must not end with a slash.
  • options {?Object} An object of options.

Returns:

  • {Object} The created instance.

.attributes()

Gathers and returns all platform-, screen- and user-related information.

Examples:

const attributes = ackeeTracker.attributes()
const attributes = ackeeTracker.attributes(true)

Parameters:

  • detailed {Boolean} Include personal data.

Returns:

  • {Object} User-related information.

⚙️ Instance API

Each ackeeTracker instance is an object with functions you can use to track visits and events.

.record(domainId, attributes, callback)

Creates a new record on the server and updates the record constantly to track the duration of the visit.

Examples:

instance.record('hd11f820-68a1-11e6-8047-79c0c2d9bce0')
instance.record('hd11f820-68a1-11e6-8047-79c0c2d9bce0', {
	siteLocation: window.location.href,
	siteReferrer: document.referrer
})
instance.record('hd11f820-68a1-11e6-8047-79c0c2d9bce0', undefined, (recordId) => {
	console.log(`Created new record with id '${ recordId }'`)
})
const { stop } = instance.record('hd11f820-68a1-11e6-8047-79c0c2d9bce0')

// Manually stop updating the visit duration. The returned function should be used in
// single-page applications. Call the function when the user navigates to a new page
// before creating a new record.
stop()

Parameters:

  • domainId {String} Id of the domain.
  • attributes {?Object} Attributes that should be transferred to the server. Will be ackeeTracker.attributes() unless specified otherwise.
  • callback {?Function}({?String}) Function that executes once the record has been created. Receives the id of the new record.

Returns:

  • {Object} Object with a stop function. Call the returned function to stop updating the visit duration of the created record.

.updateRecord(recordId)

Updates a record constantly to track the duration of a visit. You usually don't need to call this function, because .record calls this function for you. It's however helpful when you want to continue tracking a record after a page reload or after a record has been stopped.

Updating attributes of an existing record isn't possible.

Examples:

instance.updateRecord('dfa929d3-bfbf-43f2-9234-ed646eb68767')
const { stop } = instance.updateRecord('dfa929d3-bfbf-43f2-9234-ed646eb68767')

// Manually stop updating the visit duration. The returned function should be used in
// single-page applications. Call the function when the user navigates to a new page
// before creating a new record.
stop()

Parameters:

  • recordId {String} Id of the record.

Returns:

  • {Object} Object with a stop function. Call the returned function to stop updating the visit duration.

.action(eventId, attributes, callback)

Creates a new action on the server to track an event.

Tipps:

  • key won't show up in the Ackee UI for every event type, but must be specified nevertheless
  • Use 1 as value to count how many times an event occurred or a price (e.g. 9.99) to see the sum of successful checkouts in a shop
  • Reset an existing value using null when the user canceled an event (e.g. removed an item from the checkout)

Examples:

instance.action('513a082c-2cd5-4939-b417-72da2fe1761d', {
	key: 'Checkout',
	value: 9.99
})
instance.action('1b6e20cb-7c7d-48ca-8cb6-958a55d7a9e3', {
	key: 'Subscription',
	value: 1
}, (actionId) => {
	console.log(`Created new action with id '${ actionId }'`)
})

Parameters:

  • eventId {String} Id of the event.
  • attributes {Object} Attributes that should be transferred to the server.
    • key {String} Key that will be used to group similar actions in the Ackee UI.
    • value {?Number} Positive float value that is added to all other numerical values of the key.
  • callback {?Function}({?String}) Function that executes once the action has been created. Receives the id of the new action.

.updateAction(actionId, attributes)

Updates an action on the server.

Examples:

instance.updateAction('7fe70f50-cb16-4e27-90ab-d6210296a4b7', {
	key: 'Checkout',
	value: '4.99'
})
instance.updateAction('24776c2b-c5d6-4fac-852a-067d086dc4af', {
	key: 'Subscription',
	value: null
})

Parameters:

  • actionId {String} Id of the action.
  • attributes {Object} Attributes that should be transferred to the server.
    • key {String} Key that will be used to group similar actions in the Ackee UI.
    • value {?Number} Positive float value that is added to all other numerical values of the key.

🔧 Options

The option-object can include the following properties:

{
	/*
	 * Enable or disable tracking of personal data.
	 * We recommend to ask the user for permission before turning this option on.
	 */
	detailed: false,
	/*
	 * Enable or disable tracking when on localhost.
	 */
	ignoreLocalhost: true,
	/*
	 * Enable or disable the tracking of your own visits.
	 * This is enabled by default, but should be turned off when using a wildcard Access-Control-Allow-Origin header.
	 * Some browsers strictly block third-party cookies. The option won't have an impact when this is the case.
	 */
	ignoreOwnVisits: true
}

Miscellaneous

Donate

I am working hard on continuously developing and maintaining Ackee. Please consider making a donation to keep the project going strong and me motivated.

Links

ackee-tracker's People

Contributors

electerious avatar gempain avatar greenkeeperio-bot avatar mathe42 avatar thecodrr avatar tkw1536 avatar yehudab 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ackee-tracker's Issues

Error: Server returned with an unhandled status

Hi,

I just finished the setup of the server, everything works fine when I try Ackee with the <script> but with ackee-tracker I get an error. I tried removing parameters but no matter what I do, it still crashes when I call .record()

Here's a photo:

Screen Shot 2020-06-14 at 4 06 54 PM

And the code

    const instance = ackeeTracker.create({
        server: 'https://ackee.gawlik.io',
        domainId: 'acf48a42-b795-4202-834d-e23531572138',
    });

    instance.record({
        siteLocation: window.location.href,
        siteReferrer: document.referrer,
    });

Maybe it's stupid, but I really couldn't find the solution,

Anyway, thanks for this great tracker 👍

Cannot use events, action is not a function

I can't shake this error :

TypeError: instance.action is not a function. (In 'instance.action('...', {
            key: 'click',
            value: 1
  })', 'instance.action' is undefined)

My code is

   const instance = ackeeTracker.create('https://myservercom').record('...', 
   undefined, (recordId) => {
      console.log(`Created new record with id '${ recordId }'`)
  })

  document.querySelector('#subscribe').addEventListener('click', () => {
      console.log("subscribe");
      instance.action('...', {
          key: 'click',
          value: 1
      })
  })

Tracking POST calls get 200 response from server but nothing is stored

I need some help with debugging.

Server is running on Netlify + MongoDB Atlas

When testing, I can see the tracking calls going out:

{
  "query":"\n\t\t\tmutation createRecord($domainId: ID!, $input: CreateRecordInput!) {\n\t\t\t\tcreateRecord(domainId: $domainId, input: $input) {\n\t\t\t\t\tpayload {\n\t\t\t\t\t\tid\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t",
  "variables":{
    "domainId":"2a97e286-d2ca-4755-afb6-1addeac283e8",
    "input":{
      "siteLocation":"http://localhost:3000/",
      "siteReferrer":""
    }
  }
}

but nothing is written to the DB. The Netlify log shows /api function is called but doesn't provide any other useful info

API response is:

{
    "data": {
        "createRecord": {
            "payload": {
                "id": "88888888-8888-8888-8888-888888888888"
            }
        }
    }
}

Note:

"domainId":"2a97e286-d2ca-4755-afb6-1addeac283e8" 

is correct. Also i've set

 ignoreLocalhost: false,

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.

Client-side routing

When adding ackee-tracker using Next.js and there is client-side routing I could see that the POST request sent doesn't use the current URL in the browser, but instead, the first page the user entered.

I will try to make a PR that fixes this issue.

Supporting typescript out of the box

Hey :) I just wanted to ask if there is any plan on supporting typescript (e.g. shipping / publishing types) natively? There's already a @types/ackee-tracker with third-party types...

Option to switch off interval PATCH

It would be great to manually set an option per website to disable interval PATCH pinging with the rest of the options in data-ackee-opts attribute.

As I understand time spent on site is not yet displayed on Ackee's frontend and some people may not need this functionality.

The script causes visible layout issues when loading

The Firefox console notifies me that:

Layout was forced before the page was fully loaded. If stylesheets are not yet loaded this may cause a flash of unstyled content.

It also says that the problem is at 1:15966, aka the 15,966th character in the script.

It is correct, as I was able to see repainting occur, where the style loaded once incorrectly, and then was corrected. This doesn't happen when I remove the script, but occurs no matter where I place it, at the bottom, at the top, without async, with defer, etc.

Option to Disable

I know there's an ignoreLocalhost option but I develop using docker behind a reverse proxy so my sites have real URLs in development. It would be cool to have an option to just disable to the tracker so I could do something like

disable: process.env.ENV === 'prod' ? false : true

Or the inverse to enable it. Or maybe I'm missing something somewhere and you can totally do this already some other way.

Automate `record` functionality (especially for SPAs)

The idea here is to add opt-in functionality for automating the record functionality. My thought is that we could add a .watch() method that would...

  • Call the initial .record() function to initialise the record
  • Attach a listener to the window for popstate, calling .record() if the path has changed

The docs for this method would look something like this...


.watch(domainId, attributes, config)

Initialises a record and keeps it up-to-date when popstate events occur.

Examples:

instance.watch('https://ackee.example.com', {
	detailed: false,
	ignoreLocalhost: true,
}, {
	immediate: false,
})

Parameters:

  • domainId {String} Id of the domain.
  • attributes {?Object} Attributes that should be transferred to the server. Will be ackeeTracker.attributes() unless specified otherwise.
  • config {?Object} Configuration for the watcher.
    • config.immediate {?Boolean} Whether or not to call .record() immediately. If false, instance.record() must be called before instance.watch() to ensure the initial page is tracked. Defaults to true.

Wrong Host header send

Hi there 👋

Great work on ackee, I started to use it for NuxtJS examples.

We encountered one issue today on our first example: https://xr8nr.sse.codesandbox.io

We have a CORS error, and it seems that no HOST is sent:
Screenshot 2020-03-24 at 17 56 42

When we setup the ACKEE_ALLOW_ORIGIN to "https://xr8nr.sse.codesandbox.io" on our Heroku (https://nuxt-ackee.herokuapp.com), we had a CORS error, so we set it to *.

When looking at the request headers on Chrome, we have the wrong host header:
Screenshot 2020-03-24 at 17 41 37

So it fails directly here: https://github.com/electerious/Ackee/blob/master/src/server.js#L56

Any idea about what we can do wrongly?

Also, we created a nuxt-ackee module ✨

Allow instance ID to be saved to localStorage

I have a use case where I expect that users may reload the webpage but I would like to treat all of their time spent across multiple tab reloads as part of the same visit.

Would it be possible to expose an ID on the instance that could be saved to localStorage and set on a new instance if the page is reloaded?

How to use it basicly ? (what is domainId ?)

<script async src="https://ackee.example.com/tracker.js" data-ackee-server="https://ackee.example.com" data-ackee-domain-id="hd11f820-68a1-11e6-8047-79c0c2d9bce0"></script>

"domainId {String} Id of the domain." extract from the doc but none steps to have it ...
src => ok
data-ackee-server => ok
data-ackee-domain-id => ???

How to create it (data-ackee-domain-id) ? can I fill random string myself ?

More Meta Data

Can we have something to post some meta data for example
currentLoggedInUsers
Windows (for modal popups in the App)

What are/is the API URL(s)?

Hello,

I am trying to lock down my instance using Cloudflare Access and they utilize zero-trust access management meaning that all URLs require additional authentication by default, so I am wondering what API URL(s) I need to whitelist so users can still report data, while keeping the admin panel protected.

Edit: I wanted to note that I already have /tracker.js whitelisted, I am talking about the API endpoints that are posted to using the tracker.js script.

Thanks!

The perks of embedding the tracker

In the installation docs, you mention that "We recommend installing ackee-tracker using npm or yarn.".

Though I do see an advantage of doing this, which is to remove the need of having a script tag as the code will be embedded in your pages (also bypasses ACKEE_TRACKER, I am worried that the drawback is you have to make sure your version of the tracker is aligned with that of the server, which is something you don't have to worry about when you reference the script from your server (assuming they are natively in sync).

So, I was wondering whether it's recommended to use an embedded version or generally better to use a script. In any case, it might be a good idea to mention in the readme that if you embed the code, you'll have to manually ensure your tracker is in line with your server.

That said, I don't think mis-alignment will happen often. But when it does, you'll have to re-deploy all your site.

Option to exclude IPs

I'm authoring a blog and would like to exclude tracking authors/site administrators when they access the website. The IPs from which they access the site are well known, so an option to exclude a list of IPs from tracking would be nice.

Enable more data at ackee-tracker

Hi,
I just installed Ackee, and it is wonderful, simple and direct to the point.
However, I cannot get device data, browser and other related data. I am getting this message:

There is either no data available or collecting detailed data is disabled in ackee-tracker.

How can I enable device and browser data analytics?

Screen Shot 2021-08-31 at 12 03 51

Best,
Hamza

Log ignored records/actions on localhost?

Currently when ignoreLocalhost is set to false, there is a single console.warn message but no other info for troubleshooting your app. When you are new to Ackee or using it a new framework or pattern, it would be nice if you could get some indication of what would have been tracked. For example, you could console.info something like:

ackee record <domainId> - <recordId>
ackee record update - <recordId>
ackee action <key> - <recordId>
ackee action update - <recordId>

(unsure if the updates should be logged, but seems right at least for actions whose updates will be manually driven)

Would you accept a PR adding functionality along these lines? If so, design questions follow.

What is your preferred API for this?

  • Expanding existing key: ignoreLocalhost: true | false | 'log' (most straightforward)
  • New key: ignoreLocalhostBehavior: 'log' | 'silent' or logOnIgnoreLocalhost: true | false etc (or verbose: true | false which could be independent from ignore if people want this in prod for some reason)

Would you prefer updates be logged? Or just creates? Configurable (logOnIgnoreLocalhost: 'create' | 'all' | false)?

Would you prefer the logging instance augment all of the standard behavior? Maybe something like

// new function with same API as send
const log = function(url, body, options, next) {
  // probably inspect body.variables to determine what mutation type is happening, though could also parse query string
}

export const create = function(server, options) {
  // added to body of create and replaces existing direct calls to `send` in this function
  const _send = options.ignoreLocalhost === 'log' ? log : send;
  ...

I think this is probably the right path forward for best simulation, and it means calls to stop don't need to be logged since the intervals will just stop happening.

This would also be useful in something like electerious/use-ackee#10.

Parse UA on the server-side

Why is the parsing of the UA done on the client side, and not the server side?
You could potentially save 15kB (~8kB gzip). It's not much, but it can be done server side.

Systems without version number don't show up if version number is enabled

Some systems report only the system without a version number. In this case you can only see these systems in the statistics, when you use the "hide system version" button.
It would be great if these were also shown just without a version number, in between the other entries with a version number.

Filter out bots

Does the tracker record bots that are visiting the site? If so, is there a way to filter that out other than directly manipulating the DB?

Too many visitors with Gatsby / React app

I'm trying to add Ackee tracker to my Gatsby project, without using the gatsby plugin as it seems out of date.

In my understanding, you should

  • create a single instance of Ackee tracker
  • create a new record on each page change (end .stop() the previous record, if any

I've implemented this pattern, but unfortunately my "Active visitors" count is increased on each page change, even though I can confirm that there only a single instance of Ackee tracker created.

Here is my gatsby-browser.js:

import React from "react"
import { Ackee } from './src/hooks/use-analytics';

export const wrapRootElement = ({ element }) => (
  <Ackee>{element}</Ackee>
)

and use-analytics.js:

import React, { createContext, useContext, useEffect, useState } from 'react';
import * as ackeeTracker from 'ackee-tracker';

const AckeeContext = createContext(undefined);

export const useAckee = () => useContext(AckeeContext);

export function Ackee(props) {
  const [ackee] = useState(
    process.env.GATSBY_ACKEE_SERVER && process.env.GATSBY_ACKEE_DOMAIN_ID ? ackeeTracker.create({
      server: process.env.GATSBY_ACKEE_SERVER,
      domainId: process.env.GATSBY_ACKEE_DOMAIN_ID,
    }, {
      ignoreLocalhost: process.env.GATSBY_ACKEE_IGNORE_LOCALHOST !== 'false',
      detailed: process.env.GATSBY_ACKEE_DETAILED !== 'false',
    }) : undefined,
  );

  const [record, setRecord] = useState();

  const navigate = (path) => {
    if (record) {
      record.stop();
    }
    if (ackee) {
      setRecord(ackee.record({
        siteLocation: `${window.location.origin}${path}`,
      }));
    }
  };

  useEffect(() => {
    // first record
    if (ackee) {
      setRecord(ackee.record());
    }
    return () => {
      if (record) {
        record.stop();
      }
    }
  }, [ackee]);

  return (
    <AckeeContext.Provider value={navigate} {...props}/>
  )
}

In my app, in my side nav component, I do this:

...
const pathChange = useAckee();

const onClick = () => pathChange(path);
...

This works very well:

  • when the app loads, I get a record for a new page load on the proper url
  • when the user navigates via a React link, I also get a new page load with the proper url

But, my Active visitor counter is not correct.

Any idea ?

Warning fills logs

Hello.

I'm building server side rendered apps with Next.js. My logs get filled with: "Ackee is not executing automatically because you are using it in an environment without a window object'". It would be great if this was removed or only logged once.

Thanks

console.warn('Ackee is not executing automatically because you are using it in an environment without a `window` object')

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.