GithubHelp home page GithubHelp logo

ankane / ahoy.js Goto Github PK

View Code? Open in Web Editor NEW
486.0 18.0 117.0 161 KB

Simple, powerful JavaScript analytics

License: MIT License

JavaScript 93.92% HTML 6.08%
analytics first-party-analytics visits events

ahoy.js's People

Contributors

ankane avatar buschtoens avatar fleitz avatar hwhelchel avatar jakeniemiec avatar kremalicious avatar miguelfrias97 avatar pazaricha avatar pelletencate avatar richardvenneman avatar teohm avatar thejullius avatar wa0x6e avatar wheeyls avatar willcosgrove 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ahoy.js's Issues

Update the no-jquery branch

Hello,
We have a React frontend app that relies on the no-jquery branch of your gem which is a bit outdated now (and we have problems with duplication of cookies with httpOnly/sameSite, etc). Do you plan on maintaining it or should we drop it to use something else ?

Events that occurred on different days have the same visit token

We noticed that ahoy_events on different days have the same visit_id which are attributed to ahoy_visits.

Based on the text from the Readme, wouldn't events have different visit IDs if it's been over four hours?

Readme:

The visit token expires after 4 hours, in which a new visit is created. Visits are useful for tracking metrics like monthly active users. The visitor token expires after 2 years. .

On a side note, we have some ahoy_event records from last month that have the same visit_id as records created today. How are vistors being tracked since we have no users accounts (the site doesn't have a login function), set mask_ips to True, and set cookies to False?

Post same event multiple times if you have more than one window/tab.

If you have a click event trigger ahoy.track, and that click opens a new window or tab, it will post the event twice. I think is because when window/tab loads check for eventQueue and the event is still on eventQueue.
I think the solution is to set the cookie name to ahoy_events_TIMESTAMP. So every window/tab will work on a different cookie.

I found it using ctrl + click on a anchor tag using click event.

Integration with segment.io

Hey, do you have tricks/gists to integrate Ahoy.js with Segment.io ?
Is there a way to properly forward visitor ID and event tracking to Ahoy.js ?

I am using Ahoy on my Rails backend and it works great, but with our new React based Frontend we'd like to use some dispatcher service like Segment.io to avoid having to dispatch events everywhere.

Send cookies on requests to another domain

I've been using the ahoy.js library to create ahoy events on a rails server on a different domain which has the ahoy gem configured. The events are being created successfully. However, I need to send the cookies on the request, because the server gets some extra data from that.
The above requires the following option to be set on the ajax request:

xhrFields: {
  withCredentials: true
}

Is there an option on ahoy.js to make this work?

I'm setting ahoy config in this way:

ahoy.configure({
  urlPrefix: 'http://otherdomain.com'
});

Ahoy.js 1.0

Ideas

  • Use navigator.sendBeacon by default
  • Remove jQuery dependency
  • Add setProperties method

visitParams is not sending with trackView

Hello again open source hero, ankane. 💪

Our visitParams is not sending with trackView. I followed the instructions in the Ruby ahoy repository and dug through the code, but I can't tell why this isn't working, and there's no documentation to explain it that I can see.

Using the example from the Ruby repository in our Vue router:

router.afterEach(route => {
  // we want to send some extra stuff here
  ahoy.configure({ visitParams: { referralCode: 123 } })
  ahoy.trackView()
})

Nothing in visitParams appears in the payload.

Ability to configure own headers for the HTTP request

In order to handle non-cookie authentication for API backends (and set the current_user to attach events and visits), we need to be able to add custom headers to the request being sent.

In our case, we are doing Authentication via JSON Web Token passed via either headers or URL parameters. We would need to be able to configure those headers either dynamically on every call or maybe better, after we authenticate the user frontend-side.

[Idea] Remove TailwindCSS classes from "class" attribute in ahoy.js

Hi there! Love using ahoy, I think it's a great product. Thanks to all who has worked on it.

I did a quick search through the issues but wasn't able to come up with any relevant questions, so here goes:

Using tailwind CSS adds a lot of classes to our button elements. When I click on a button this is the tracking JSON that gets pushed to ahoy.

[
   {
      "name":"$click",
      "properties":{
         "tag":"a",
         "class":"appearance-none cursor-pointer flex focus:border-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 font-sans font-medium rounded-full transition ease-out duration-300  text-2xl justify-center px-4 mt-6 mr-6 md:mt-8 md:mr-8 custom-class",
         "page":"/redacted/redacted",
         "text":"close",
         "href":"http://redacted.com"
      },
      "time":1643737795.999,
      "id":"fd57268c-34f8-4726-a00a-f4d96d320df6",
      "js":true
   }
]

Specifically what I am interested in is removing a lot of the cruft that comes along with the class attribute.

I wonder if we should give people the option to filter out certain classes that provide no value to tracking? In this case I'd want to filter out every class except custom-class at the end.

So, desired tracking output would be:

[
   {
      "name":"$click",
      "properties":{
         "tag":"a",
         "class":"custom-class",
         "page":"/redacted/redacted",
         "text":"close",
         "href":"http://redacted.com"
      },
      "time":1643737795.999,
      "id":"fd57268c-34f8-4726-a00a-f4d96d320df6",
      "js":true
   }
]

Thanks in advance!

What doest ahoy.js able to do without cookies

We install ahoy gem and ahoy.js on a project today to use it. So I'm looking on configuration to know how it works depending of some configs.

And I would like to know if ahoy.js do something if cookies is set to false. From my code reading it looks like not. But I would like to be sure.

Expo Support?

I see there is dedicated iOS and Android support. When I tried importing ahoy.js into a react native/expo project, I was unable to get the library working.
IMG_4607

Will do some research and report back, I couldn't find anyone trying something similar online.

Support skipping certain tracked events inside a [data-no-track] tagged element

I have a use-case where I have trackClicks() turned on, but for certain interactions, I want to fire my own event, not just a generic $click. I would prefer not to get double events, so I need a way to disable the overall trackClicks functionality for this part of my page.

So I made the onEvent function ignore the matched element if the matched element also matches on [data-no-track] *, [data-no-track]. This will let me either put a data-no-track attribute on the <a> itself or in a parent of the <a>.

I would be happy to submit a PR if you find this functionality useful.

ahoy.track() - no implicit conversion of Array into String

Ahoy is working correctly 99% of the time, but once in a while we are getting "no implicit conversion of Array into String" errors

Instead of {"name": "My Name", "properties": { ... }} it is posting that wrapped as an array ([{"name": "My Name", "properties": { ... }}]) to /ahoy/events

We have seen occurrences on windows and mac, chrome and firefox.
It seems like every pageview of an affected user will trigger the error.

FYI: ahoy/events routes are now blocked by EasyPrivacy block list

Just noticed when testing some analytics locally, the beacon did not fire.

https://github.com/easylist/easylist/blob/master/easyprivacy/easyprivacy_general.txt#L487

Seems to be, it was added 13 days ago.

To make analytics still work, if that is desired, then one needs to change the path:

# config/initializers/ahoy.js
Ahoy.api = false

# config/routes.rb
 mount Ahoy::Engine => "/ahoyyy"

# app/.../ahoy.js
 ahoy.configure({
    visitsUrl: "/ahoyyy/visits",
    eventsUrl: "/ahoyyy/events",
  })

[Idea] The ability to update a visit, or be able to start a visit programmatically.

Here is the use case:
The app is a ruby rails app, that serves HTML so no real sense of a Javascript application.

I am generating a fingerprint using fingerprintjs, which returns the result with a callback. This callback sometimes returns quickly or slowly, which seems to be based on the browser. For example in chrome it returns quickly, and on Firefox it returns slowly.

And in some cases, the visit has already been created. So when I call ahoy.configure in the callback the visit is already created and the fingerprint is never set.

A couple of thoughts:

  • whenever configure is called it updates the visit.
  • createVisit is exposed or a new helper method is created upsertVisit.

Other ideas? Am I thinking about this incorrectly?

Create option to configure visitTtl and visitorTtl

Hello, our team uses your lib and we had some difficulties with the default value of visitTtl and visitorTtl, mainly because of visitTtl.

Basically, our session token expires in thirty days, while the ahoy_visit cookie expires in four hours. After four hours, the ahoy_visit cookie is renewed and our backend loses control of the events because a new visit_token is created.

Our suggestion is to keep the default valves, but create a option to configure these values on the configure function.

I will send a PR with the code change and, if it makes sense, let me know and I will update the documentation as well.

TypeError: Object(...) is not a function, upgrading from 3.4 to 3.5

I have been successfully using ahoy.js 3.4 inside vuex without any issues. With the following command:

this._vm.$ahoy.track('start', { id: 'ABC' })

After upgrading to 3.5, when trying to execute the same command I get the following error:

TypeError: Object(...) is not a function

It gets thrown by this line inside the trackEventNow function

window.navigator.sendBeacon(eventsUrl(), objectToFormData(data));

I think it might be due to this object-to-formdata upgrade:

cc90625

What would be the correct way to use the track funcion with the new version of the upgraded object-to-formdata library?

Cross-Origin Read Blocking (CORB) blocked cross-origin response

Our frontend Ionic web app is running on a different server than our backend Rails API, trying to get Ahoy Rails wired up to post events however getting Cross-Origin Read Blocking error.

Cross-Origin Read Blocking (CORB) blocked cross-origin response http://localhost:3000/ahoy/events with MIME type application/json.

Is it possible for ahoy.js to track events to a different server than Ahoy Rails? Would I need to expose my own API endpoint to receive the track events from ahoy.js?

documentReady block is triggered before configure has had a chance to run

We're loading ahoy up like this (from GTM):

<script type="text/javascript" src="//path_to_ahoy/ahoy-0.3.2.js"></script>

<script>
  ahoy.configure({
    cookieDomain: "ourdomain.com"
  });
  ahoy.trackAll();
</script>

We execute this both on our naked domain and a subdomain. So, obviously setting cookieDomain is important or we'd get double cookied and/or bad things™️ would happen.

It appears to me that this thing: https://github.com/ankane/ahoy.js/blob/master/src/index.js#L438-L442 is triggered before the configure block has had a chance to execute.

I've currently 'fixed' this by hardcoding our domain into the lib itself here: https://github.com/ankane/ahoy.js/blob/master/src/index.js#L8 and that seems to fix things up nicely.

Would it make sense to remove the documentReady block from the lib itself and give control of that to the end user to execute after configure has had a chance to run?

Why visitsUrl and eventsUrl should use double // on my side

Hi @ankane,
i'm using your amazing ahoy.js

It doesn't seem like a problem, but just to be sure. Is this a bug or should it be like this? So i tried to configure my ahoy.js like this

ahoy.configure({
  urlPrefix: process.env.VUE_APP_BASE_API,
  visitsUrl: "//ahoy/visits",
  eventsUrl: "//ahoy/events",
  page: "landing-page",
  platform: "Web",
  useBeacon: true,
  startOnReady: true,
  trackVisits: true,
  cookies: true,
  cookieDomain: null,
  headers: {},
  visitParams: {},
  withCredentials: true,
  visitDuration: 4 * 60, // 4 hours
  visitorDuration: 2 * 365 * 24 * 60 // 2 years
})

on visitsUrl and eventsUrl should always use double // if I use single / it doesn't send any action to the backend. and by the way my env variable contains something like this http://localhost:3000

can you clarify to help me? Thanks in advance

Unclear how the call to /ahoy/visits works

Hi there, I'm trying to get UTM parameters recorded in Ahoy using this library. They always appear blank, even though trackView() stores the full URL correctly in the visits table.

I see some information about landing_page and how a POST to /ahoy/visits sends this along with the tracking tokens.

However, watching my Chrome network tab, the only API calls made are to /ahoy/events.

Has this behaviour changed, and the README is not up to date?

Add the option to keep the ahoy_visit cookie alive

Currently, the ahoy_visit cookie is only renewed if a server API is called, which the AhoyController on the server side extends the ahoy_visit cookie's expiration date.

This becomes problematic when the user stays idle the page, but whose actions should still be considered to belong to the same ahoy visit when they resume.

Could we have an option in ahoy to start a timer that automatically extends the ahoy_visit cookie's expiration date?

Click event is duplicated when redirect from A.html to B.html

I'm a fresher. I'm having problem using Ahoy.js.
I have 2 sample file HTML include Ahoy.js.
Sample A:

<a href="B.html"> <img src='a.jpg'> </a>

Sample B:

<button>Add Cart</button>

I click a tag, when redirect to 'B.html', maybe eventQueue is still saved from A.html, so it should be duplicated event when send request via Ajax.

Can anyone help me??
Thanks you!.

Address CORS policy change in Chrome 59?

Chrome just changed the way they handle cross-origin sendBeacon requests.

https://bugs.chromium.org/p/chromium/issues/detail?id=490015

From what I understand, they don't want cross origin requests to be able to send JSON, but they are allowed to send plaintext. It will be up to the server to deal with the difference in format and deal with the request accordingly.

We got dinged with this in our implementation, because right now we host the JS on our www domain, and send CORS requests to our track subdomain. Our current plan is to change the way we host the file so that the CORS isn't required, but I'm curious if you think that this is worth updating the library to handle this scenario?

Add debug messaging around sendbeacon

In reference to #64

This issue is currently causing a lot of TypeError: Illegal Invocation error metrics. I don't think it will be very easy to provide a way to reproduce but would it be possible to improving the visibility into the circumstances surrounding the exceptions being thrown? The error it self doesn't give very much info on why it's taking place. Would it be possible to add a try catch to give useful debug output and rethrow, such as an output of eventsUrl() and data and index_module_1's return in order to help us with debugging the Illegal Invocations?

Next js and ahoy

Hello, i am getting issues with ahoy, I am including ahoy.js in the DOM. And when it is loaded and app is loaded I am doing

ahoy.configure(config) // my configuration
then I do

ahoy.trackView();
ahoy.trackClicks("a, button, input[type=submit]");
ahoy.trackSubmits("form");
ahoy.trackChanges("input, textarea, select");

But first POST requests goes to wrong URL (the default ones from ahoy.js) and I am getting 404. Can I avoid this somehow?

ahoy.configure is ignored?

So I have code that is calling ahoy from a Wordpress front-end to post to a Rails backend (part of the site is dynamically served from rails APIs).

I have ahoy.configure set as such (my API's run from /flip).

    ahoy.configure({
      urlPrefix: "",
      visitsUrl: "/flip/ahoy/visits",
      eventsUrl: "/flip/ahoy/events",
      cookieDomain: null,
      page: null,
      platform: "Web",
      useBeacon: false,
      startOnReady: true
    });  

Sometimes, I see it working and events are being added to the database, but for click events I'm getting 404 errors where it is trying to find the events at <domain>/ahoy/events.

Where and when should configure be called? Is it enough to call it on document.load?

documentReady function triggers start before configuring ahoy

Hi! first of all thanks for this useful tool.

I was having some troubles finding out why on the first page load, visitsUrl was pointing to the default URL 'ahoy/visits' and not the one I set up with the configure method. I find out that the issue is related to the documentReady function call at the end of library source code.

  documentReady(function() {
    if (config.startOnReady) {
      ahoy.start();
    }
  });

  return ahoy;

The problem is synchronization, by the time the library module is required, is very likely that the DOM content has already been loaded, calling the documentReady function with the default parameters that are inside the library source code (where startOnReady. is set to true, mine is set to false). Due to some requirements I'm using require.js that is being loaded after the HTML body tag and it's difficult for me to change this.

I writing this issue also as a reminder, I will like to make a pull request offering an alternative solution when i have some time. I can just change the default config object, but it would be better if it supports my use case.

Let me know what you think or if there's another step or solution that I'm missing.

Thanks!

nextjs import issue (solved)

Hi @ankane
Really thanks for your awesome work both client and server.

I use this package with nextjs and there was an issue when importing this module.

*Step to re-create this issue.

  1. create next-app by using https://github.com/segmentio/create-next-app
  2. import ahoy.js in pages/index.js
...
import ahoy from 'ahoy.js'
...

It shows error
2019-02-28 22 18 58

*Workaround to solve this issue

1. dynamic import
window is not defined is well known issue and I tried the well-known solutions.

...
import dynamic from 'next/dynamic'
const ahoy = dynamic(() => import('ahoy.js'), {
  ssr: false
})

then, in componentDidMount call ahoy method.

...
componentDidMount () {
  ahoy.track('test')
}

2019-02-28 22 29 59

=> I have no idea why this doesn't work.

2. require module in componentDidMount

componentDidMount () {
   this.Ahoy = require('ahoy.js').default
   console.log('Ahoy!', this.Ahoy.track('Hello!'))
 }

2019-02-28 22 35 15

=> This worked. (Post 501 error is not a problem)

3. Final Code
somewhere in project
ex: utils/customAhoy.js

import Cookie from 'js-cookie'

const dev = process.env.NODE_ENV !== 'production'
const baseURL = dev ? 'http://api.localhost:3000' : 'https://api.example.com'

const isServer = (typeof window === 'undefined')
let ahoy

if (!isServer) {
  ahoy = require('ahoy.js').default
  ahoy.configure({
    urlPrefix: '',
    visitsUrl: `${baseURL}/ahoy/visits`,
    eventsUrl: `${baseURL}/ahoy/events`,
    page: null,
    platform: 'Web',
    useBeacon: true,
    startOnReady: true,
    trackVisits: true,
    cookies: false,
    cookieDomain: null,
    headers: {'Authorization': `Bearer ${Cookie.get('accessToken')}`},
    visitParams: {},
    withCredentials: true
  })
}

export default ahoy

somewhere in project you want to use ahoy
ex: index.js

import React from 'react'
/* import configured ahoy */
import ahoy from 'utils/customAhoy'

export default class Index extends React.Component {

  componentDidMount () {
    ahoy.trackAll()
  }

  render () {
    return (
      <div />
    )
  }
}

I just reported this if someone has same trouble. If someone have a better solution, please let me know.

Thanks.

TypeError: Illegal invocation

getting TypeError: Illegal invocation
The stack trace’s top layer stops at window.navigator.sendBeacon(eventsUrl(), index_module_1(data) which comes from ahoy.js

Calling function is ahoy.trackView()
Errors are not confined to any particular browser or device.

ahoy.track not posting request

I am sorry if this is actually a JS question and not an Ahoy one, I'm a beginner at both of them.

I would like to track certain elements of my page, so I bind a function to their "onClick" to perform an ahoy.track(...). However, nothing happens! If I go to Firefox's console and write ahoy.track("bla",{}). If I click the 'network' tab, I see that no http post request is sent to (xxx/ahoy/event).
When I click enter, the only thing that happens is the

Am I understanding something wrong? Shouldn't ahoy.track send a post to the server?

Thanks!

Open to moving some helper functions to exports?

We're experimenting with Ahoy. One thing we've noticed is that using the default submit tracking sometimes conflicts with custom forms we have with an onSubmit event. We've worked around this by manually hooking those forms up to fire ahoy.track as part of their onSubmit function, but part of doing so involved copying cleanObject into our own code since it's not readily available.

Would you be open to a PR that promoted some of the private helper functions to exports? One possible idea here would be to extract the code in iteration within trackSubmits https://github.com/ankane/ahoy.js/blob/master/src/index.js#L454-L457 into its own trackSubmit function so that it could be individually applied to forms.

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.