keen / keen-tracking.js Goto Github PK
View Code? Open in Web Editor NEWA light, fast and flexible javascript tracking library
Home Page: https://keen.io
License: MIT License
A light, fast and flexible javascript tracking library
Home Page: https://keen.io
License: MIT License
I'm trying to turn off event-logging in dev
environment, but Keen.enabled = false
doesn't seem to do the trick (as evidenced by viewing my collections in the keen dash). Is there another step I have to take?
The project is react
using webpack
// keen-config.js
import Keen from 'keen-tracking'
export const initKeen = () => {
const client = new Keen({
projectId,
writeKey,
})
const sessionCookie = Keen.utils.cookie('wayhome-cookie')
if (!sessionCookie.get('visitorID')) {
sessionCookie.set('visitorID', Keen.helpers.getUniqueId())
}
const sessionID = Keen.helpers.getUniqueId()
const sessionTimer = Keen.utils.timer()
sessionTimer.start()
client.extendEvents(() => {
// yadda yadda yadda
})
return client
}
// index.js
const client = initKeen()
window.Keen = client
if (process.env.NODE_ENV === 'development') {
console.log("DISABLING KEEN")
Keen.enabled = false
}
The console.log
statement fires, so I know my conditional is working.
var cookie = Keen.utils.cookie('test-cookie');
// cookie.get('some-unstored-value');
// now returns {}, but should return `null`
These guides should be ported into this repo as example content and improved to make use of the latest and greatest helpers and utilities: https://keen.io/docs/streams/video-tracking/
Let's create and link to jsFiddles for each one as well.
References:
Hello!
When I started using getDatetimeIndex()
, I assumed that it would be returning the time for UTC. I had to read the MDN page for Date() to realize that it was browser-local time. I think it would be handy to document this and perhaps also show how to get the DT in UTC[1]:
var now = new Date();
var now_utc = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());
var utcDatetimeIndex = Keen.helpers.getDatetimeIndex(now_utc);
Thank you for your time and effort on this!
Cheers,
Fitz
[1] Adapted from: http://stackoverflow.com/a/6777470
I'm not seeing the web auto collector in any of the keen repos. Maybe I'm blind. I think it just sits on top of keen-tracking. It works great, but I think I need to extend it a bit to add some autofill type features. keen-tracking can pretty much be setup to do what it is doing, but it'd be nice to start somewhere a little higher up.
I can see the non minified code at https://d26b395fwzu5fz.cloudfront.net/keen-web-autocollector-1.0.8.js , but it is all webpackified. Be nice to see the source source.
Thanks!
It is not up to keen-tracking
to attempt to patch the working environment. json3
can be a peer dependency, but it really shouldn't be even that.
Add a note to the ./README.md
that for keen-tracking
to work, window.JSON
must be present.
Now you are adding an extra 42.28kB to everyones bundle because some (what? I don't know a single browser that does not implement window.JSON
) browsers do not implement it.
index.js adds the callback to recordDeferredEvents:
Line 17 in 7500e19
However after this is called once, the queue is overwritten and the callback is lost:
keen-tracking.js/lib/defer-events.js
Line 73 in 7500e19
This means that the queue fills up and recordDeferredEvents isn't called again.
Cross-post from here: keen/keen-js#319
Create an AngularJS example implementation for our /docs/examples
directory: https://github.com/keen/keen-tracking.js/tree/master/docs/examples
I got the following error on my production server today:
<html>
^
SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
at IncomingMessage.<anonymous> (/app/node_modules/keen-tracking/lib/record-events-server.js:206:22)
The error occurs at /app/node_modules/keen-tracking/lib/record-events-server.js:206:22
where you have: var res = JSON.parse(body), error;
It's been my experience that you should always wrap any call to JSON.parse
in a try/catch
block.
I'm sure that's not enough for a fix - seems like the keen server is returning an html body instead of json - so you might have a bigger issue here, and I'm not even sure if I was sending something invalid in my request (because the error, as you can see, cannot be parsed).
Looks like retryDelay got renamed but not all references were updated.
Rename happened here: 04b6bef
The README claims there is a writePath
config property:
`writePath: '/3.0/projects/YOUR_PROJECT_ID/events'`
host and writePath: these options can be overwritten to make it easier than ever to proxy events through your own intermediary host.
Yet it seems completely ignored. Searching the codebase for writePath only find matches in the README.
I'm writing a seed script that records some predefined events for development purpose. But the script never finishes, and I was stuck for a few hours until I find out that this lib sets an interval and that prevents node process from exiting.
It would be great if I could stop that interval when my script finishes sending the events so that the process can exit normally.
For now I'm forcing process.exit()
when I'm done.
The readme mentions the Keen.deferDomEvents
function, but it doesn't seem to exist in the codebase.
Youtube is discontinuing support for v1 of the YouTube analytics api on October 31st. We should check to see what if any changes are required for https://keen.io/docs/streams/video-tracking/#youtube-video-tracking.
YouTube's made a migration guide is available here - https://developers.google.com/youtube/analytics/migration
Base64 strings occasionally contain special characters (most notably, +
). Right now keen-tracking does not URL Encode the base64 encoded data
attribute before sending it. In certain scenarios this causes the URL to break, and the Keen API barfs.
keen-tracking-1.1.3.min.js
, as many times as it can per second, completely locking up the tab process indefinitely (unless you're very patient, this usually means killing the whole browser process and all tab memory). On my MacBook Pro that's 200k times in 5-10 minutes.I believe the reason is this line: https://github.com/keen/keen-tracking.js/blob/master/lib/browser-async.js#L8
s.onload = s.onerror = s['onreadystatechange'] = function () { ...
I think that onerror
binding is causing the blocked script to attempt to load in perpetuity when something like uBlock is intercepting the request. This is obviously not okay.
I'd suggest simply killing the onerror
binding, I can't think why it'd be necessary.
What does this do? #recordEvent
and #recordEvents
are the core event transmission methods, and do all of the heavy-HTTP-lifting.
// var client = new Keen.Client({ .. });
client.recordEvent("collection", {}, function(err, res){ });
client.recordEvents({ "collection": [{}] }, function(err, res){ });
Todo:
addEvent(s)
functionality over from keen-jsA very common use case with cookie is to try to get it, and if it does not exist set it instead.
As there is no function getOrSet
, it would be great if set
would return the value instead of this
so that we could do that:
const userID = sessionCookie.get('user_id') || sessionCookie.set('user_id', Keen.helpers.getUniqueId())
Is there any internal reason for having set return this ? I haven't found any use case for that.
I think you are missing the name of the tag here in the text below on README.md. Above which tag should the snippet be pasted?
Copy/paste this snippet of JavaScript above the tag of your page to load the tracking library asynchronously.
As per documentation:
input: An object with a key of “ip” and a value of the name of the property containing the IP address to parse.
This add-on can be used with the dynamic IP address placeholder.
This doesn't work and results in a 400:
{
...anyEvents,
keen: {
addons: [
{
name: 'keen:ip_to_geo',
input: {
ip: '${keen.ip}',
},
output: 'geo',
},
]
This works:
{
...anyEvents,
my_ip: '${keen.ip}',
keen: {
addons: [
{
name: 'keen:ip_to_geo',
input: {
ip: 'my_ip',
},
output: 'geo',
},
]
am I doing it wrong?
What does this do? Keen.Client
is the core client instance constructor for all project-specific functionality. Keen.Client.prototype
will carry all of the primary methods.
// Constructor config (optional)
var client = new Keen.Client({
projectId: "YOUR_PROJECT_ID",
writeKey: "YOUR_WRITE_KEY",
host: "api.keen.io/3.0",
protocol: "https", // "http" || "auto"
requestType: "xhr" // "jsonp" || "beacon"
});
Miscellaneous methods:
// Config accessors (optional)
client.projectId("YOUR_PROJECT_ID");
client.writeKey("YOUR_WRITE_KEY");
// Get/extend base API URL, with optional params
client.url();
client.url("/events");
client.url("/events/name", { key: "value" });
Event Emitter:
client.on("some event", function(){
});
client.once("another event", function(){
});
client.off("some event");
client.emti("another event", { something: "to", pass: true });
Todo:
Is it possible to clear the data set with a call to extendEvents()
?
And, related: is it possible to check & see what the current extendEvents()
inclusions are? eg
client.extendEvents(() => {
return {
time: Keen.helpers.getDateTimeIndex(),
userId: a9sjkll3,
sessionID: Keen.helpers.getUniqueId()
}
})
// and then:
client.getEventExtensions()
/* returns:
{
time: 12345134134,
userId: a9sjkll3,
sessionID: <random uuid>
}
*/
Presence of a callback function is never checked prior to calling.
:\
What does this do? These functions return objects with commonly used sets of properties. See: https://github.com/keen/keen-tracking.js#helpers for an initial list.
Todo:
Keen.helpers = {
getBrowserProfile: function(){
return {
"cookies" : navigator.cookieEnabled,
"screen" : Keen.helpers.getScreenProperties(),
"window" : Keen.helpers.getWindowProperties()
// and many more...
};
},
getDatetimeIndex: function(obj){
var date = obj || new Date();
return {
"hour-of-day" : date.getHours(),
"day-of-week" : parseInt( 1 + date.getDay() ),
"day-of-month" : date.getDate(),
"month" : parseInt( 1 + date.getMonth() ),
"year" : date.getFullYear()
};
},
getDomEventProfile: function(e){
return {
"innerText": e.target.innerText,
"path": Keen.helpers.getDomPath(e.target).join(' > '),
"tagName": e.target.tagName,
"title": e.target.title
// and many more...
};
},
getDomNodePath: function(el){
// http://stackoverflow.com/a/16742828/2511985
// returns something like "body > div#nav > ul > a#signup"
},
getScreenProperties: function(){
// returns a curated screen profile
},
getWindowProperties: function(){
// returns a curated window profile
},
getUniqueId: function(){
// returns "f342s-3425423-dfsdfsdf12-123124fdvgdf"
}
};
I try to set utils.cookie
like your example in the Readme but I get the error
KeenTracking.utils.cookie is not a function
I am using it exactly like this
const express = require('express')
const app = express()
var KeenTracking = require('keen-tracking');
var client = new KeenTracking({
projectId: 'x',
writeKey: 'x'
});
const utils = KeenTracking.utils;
var sessionCookie = KeenTracking.utils.cookie('cookie-session-test')
It looks like cookie
is not available.
The cbResponse
variable here is undefined. Throws an error. https://github.com/keen/keen-tracking.js/blob/master/lib/utils/listener.js#L228
recordDeferredEvents() utilizes the bulk tracking function, but flushes the entire queue – if an individual event is malformed (or fails for any other reason), it is lost forever.
Current implementation for reference:
self.recordEvents(currentQueue.events, function(err, res){
if (err) {
// Retry once
self.recordEvents(currentQueue.events);
}
else {
currentQueue = void 0;
}
});
A proposed solution would be to walk through the entries in the Keen response, and emit some sort of failure for each invalid event (so the developers can implement any sort of notification/handling they wish).
Using version 1.1.2 of keen-tracking I'm getting an error when trying to use recordEvents.
I've tracked it down to a POST request to
https://api.keen.io/3.0/projects/XXXXXXXX/events/
That returns the result
{
"message": "Resource not found.",
"error_code": "ResourceNotFoundError"
}
Trying the same request on POSTMAN, it works if I remove the trailing slash
https://api.keen.io/3.0/projects/XXXXXXXX/events
for getUniqueId
I've seen a few people dislike the standard Math.random() we get in most browsers. This is the snippet we've used for generating a uuid: https://github.com/broofa/node-uuid/blob/master/uuid.js
Hello!
Most of your documentation uses snake_case key names in events. The getDatetimeIndex()
helper, and the ip_to_geo
, ua_parser
, and url_parser
addons all add fields to the event with snake_cased names. However, the getScreenProfile()
helper adds camelCased keys (colorDepth
, availHeight
, etc.) to the event. It's a minor thing, but it would be nice if there was one consistent casing used for documentation and keen-provided addons and helpers, so that when we're writing queries, we don't have to remember which casing applies to which keys. Thank you!
Cheers,
@felliott
Hey,
This is pretty cool! Might be able to help out here as I'm experimenting with some stuff on our own SDK.
Is it possible to setup a more firm structure around the following:
Nima
The internal event queue used by client.defefEvent()
and client.deferEvents()
still prevents processes from exiting in NodeJS, because the default queueInterval
is greater than 0. This hanging behavior was presumed to be fixed in the previous release, but the issue is still present for use cases where the queue is not actually used.
As a temporary workaround, the following setting will allow processes to exit properly:
const client = new Keen({
/* Configure*/
});
client.queueInterval(0);
recordDeferredEvents() utilizes the bulk tracking function, but flushes the entire queue – if the XHR fails twice in a row, these events are lost forever. This is not ideal for clients with potential connectivity issues, such as mobile devices.
Current implementation for reference:
function recordDeferredEvents(){
var self = this, currentQueue;
if (self.queue.capacity > 0) {
currentQueue = JSON.parse(JSON.stringify(self.queue));
self.queue = queue();
self.queue.options = currentQueue.options;
self.emit('recordDeferredEvents', currentQueue.events);
self.recordEvents(currentQueue.events, function(err, res){
if (err) {
// Retry once
self.recordEvents(currentQueue.events);
}
else {
currentQueue = void 0;
}
});
}
return self;
}
A proposed solution would be to add the events back into the queue upon 2x failures, rather than simply moving on.
Looks like keen-core
supports a 'protocol' option for clients, but keen-tracking enforces HTTPS even if the protocol is set to 'HTTP':
const client = new Keen({
projectId: 'PROJECT_ID',
writeKey: 'WRITE_KEY',
host: 'localhost',
protocol: 'http'
});
Can you add support for HTTP? Would be very useful for using the keen client against an internal proxy that might not support HTTPS.
Create a Vue.js Plugin example implementation for our /docs/examples
directory: https://github.com/keen/keen-tracking.js/tree/master/docs/examples
References:
add observer similar to
https://github.com/protonet/jquery.inview
that will allow you automatically recordEvent if the element appeared on the screen
Use:
https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
this will allow to help create more types of funnels based on things that people see before doing some action
What did I do?
I include the code from the Readme in my page to enable autotracking.
What happens?
Each pageview creates a new user unique id. keen
cookie is set to {}
.
What do I expect to happen?
Cookie should be set once for each user, same unique id should be used for same user.
What I think is happening
Looking at the code for cookie.prototype.set, it doesn't seem to be handling the case where 3 arguments are passed in correctly.
List proposed functionality w/ checkboxes and release version notes
Hello,
The new version 1.0.5 doesn't seem to be available in a Keen CDN, or at least I haven't found any link to it (https://d26b395fwzu5fz.cloudfront.net/keen-tracking-1.0.5.min.js
returns a 403 for instance).
Would be nice if the new version was available and the documentation updated in consequence.
What does this do? The top-level Keen
namespace will carry several sets of goodies that make robust event modeling super easy.
// Set debug to true to see console messages (if supported)
Keen.debug = false;
// Set enabled to false to disable event transmission
Keen.enabled = true;
// Used internally to log messages to the console
Keen.log( /* say something :) */ );
// Relocates current Keen namespace to a given variable and restores previous version
var K2 = Keen.noConflict();
Utilities:
Keen.utils.each(objectOrArray, function(item, indexOrKey){
});
Keen.utils.extend(primaryObject, objectToInherit);
Keen.utils.parseParams("?urlQueryString=true&value=123");
keen-tracking.js/lib/utils/listener.js
Line 212 in 73856e1
This line causes unwanted reloads when the href tag is blank/unspecified. Any example where this may happen if the element is used as a button and then handled by Javascript on the user's page.
https://github.com/keen/keen-js/blob/master/CHANGELOG.md#new-to-keen-js
Fourth argument of false
triggers a synchronous XHR request:
client.recordEvent("pageview", { key: 'value' }, null, false);
The listener
helper doesn't seem to bind events as expected. Example showing behaviour:
https://jsfiddle.net/266agghe/8/
this is an odd one :)
When using keen-tracking-1.4.0.js
for general web tracking, an element of type submit
with name of submit
(<input name="submit" type="submit" value="Go">
) generates following console error and then prevents form from submitting:
Uncaught TypeError: t.submit is not a function at keen-tracking-1.4.0.min.js:1
as a side note, if the name is Submit
(note capital 'S') then it works fine.
This project fails to start or run tests when running node versions beyond v6.
TypeError: Cannot read property 'prototype' of undefined
at Object.<anonymous> (/Users/dustinlarimer/dev/keen/keen-tracking.js/node_modules/socket.io/lib/store.js:35:41)
at Module._compile (module.js:624:30)
at Object.Module._extensions..js (module.js:635:10)
at Module.load (module.js:545:32)
at tryModuleLoad (module.js:508:12)
at Function.Module._load (module.js:500:3)
at Module.require (module.js:568:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/Users/dustinlarimer/dev/keen/keen-tracking.js/node_modules/socket.io/lib/manager.js:16:13)
at Module._compile (module.js:624:30)
This most likely means dependencies are out of date and need to be updated as well.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.