countly / countly-sdk-web Goto Github PK
View Code? Open in Web Editor NEWCountly Product Analytics SDK for websites and web applications
Home Page: https://count.ly/web-analytics
License: MIT License
Countly Product Analytics SDK for websites and web applications
Home Page: https://count.ly/web-analytics
License: MIT License
When you establish through the menu option Engagement -> Rating -> FEEDBACK WIDGETS
on Countly Community Edition Server, and create a new widget configuring that the widget must be seen on all pages, the widget is not displayed.
Do we really need to ignore all the search bots with this regex or is it just required to ignore the bots which has Javascript enabled, if the JS is disabled countly.js
sdk will not be loaded anyways. Any thoughts ?
searchBotRE = /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver|bingbot|Google Web Preview|Mediapartners-Google|AdsBot-Google|Baiduspider|Ezooms|YahooSeeker|AltaVista|AVSearch|Mercator|Scooter|InfoSeek|Ultraseek|Lycos|Wget|YandexBot|Yandex|YaDirectFetcher|SiteBot|Exabot|AhrefsBot|MJ12bot|TurnitinBot|magpie-crawler|Nutch Crawler|CMS Crawler|rogerbot|Domnutch|ssearch_bot|XoviBot|netseer|digincore|fr-crawler|wesee|AliasIO)/,
Since server accepts it now.
We could do global segments applied to all views
And local segments provided with view call
Merge them together and remove reserved keys and send to server
If I'm not mistaken, I just noticed that when you call Countly.change_id(newDeviceId)
, any events still in the queue will be attributed to newDeviceId
.
end_session
gets immediately invoked, which pushes an event straight to the requestQueue
. But the events in eventQueue
are ignored and will be sent in the next heartbeat, with the new device_id.
IMHO the only correct behaviors would be to (1) either ensure the whole remaining queue is sent out first, or (2) discard the queue.
The problem with (2) is that there is no way at the moment for me to detect that this is about to happen if I were to call change_id
, so I can't anticipate the discarding of events and take action to prevent that from happening.
All the countly calls fails with 400 and never recovers.
Steps:
Initialize countly with incorrect App key.
Run the app, let the requests fail. (with 400)
Now try to correct the app key.
Still requests fail with 400 because it is still trying to send old logs queued with old app app key.
See https://codepen.io/SgtPooki/pen/xxJKqBP?editors=1011
import countlySdkWeb from "https://cdn.skypack.dev/[email protected]";
countlySdkWeb.init({
app_key: 'nothing',
url: 'https://support.count.ly',
require_consent: true,
})
countlySdkWeb.group_features({
activity:["sessions","events","views"],
interaction:["scrolls","clicks","forms"]
});
countlySdkWeb.track_clicks()
countlySdkWeb.track_errors()
countlySdkWeb.track_forms()
countlySdkWeb.track_links()
countlySdkWeb.track_pageview()
countlySdkWeb.track_scrolls()
countlySdkWeb.track_sessions()
countlySdkWeb.track_view()
function logConsent(preMsg) {
console.log()
console.log(preMsg)
console.log('activity consent: ', countlySdkWeb.check_consent('activity'))
console.log('sessions consent: ', countlySdkWeb.check_consent('sessions'))
console.log('events consent: ', countlySdkWeb.check_consent('events'))
console.log('views consent: ', countlySdkWeb.check_consent('views'))
}
logConsent('prior to adding consent')
countlySdkWeb.add_consent('activity')
logConsent('after to adding consent')
countlySdkWeb.remove_consent('activity')
logConsent('after to removing consent')
console log output is:
"prior to adding consent"
"activity consent: " false
"sessions consent: " false
"events consent: " false
"views consent: " false
"after to adding consent"
"activity consent: " true
"sessions consent: " true
"events consent: " true
"views consent: " true
"after to removing consent"
"activity consent: " true # <-- THIS should be false
"sessions consent: " false
"events consent: " false
"views consent: " false
If we had a ajax request and append some dom elements to the document.
The track_links & track_clicks will not be triggered on those newly added elements.
After executing:
Countly.q.push(['enable_feedback', { popups: [WIDGET_ID] }]);
the website doesn't work properly (Vue project). After analyzing it, I found the following line in Countly.js:
document.body.innerHTML += '<div id="cfbg"></div>';
that is risky and should be avoided.
Some metrics like device, is not possible to obtain that easily.
We need to let SDK to accept provided values by developers and send them to server.
Similarly like NodeJS sdk does it:
https://github.com/Countly/countly-sdk-nodejs/blob/master/lib/countly.js#L1063
Example of event
{
key: "[CLY]_star_rating",
count: 1,
segmentation: {
widget_id: widget_id,
contactMe: false,
platform: "Android",
app_version: "1.1",
rating: 0,
email: "",
comment: ""
},
timestamp: Date.now(),
hour: h,
dow: dow
};
If user is inactive for more than inactivity_time, then it would not start new session when user comes back, because of session cookie
Hi,
push notifications based on FCM would be very useful.
Since there is already the android implementation, adding it to the web sdk, should be straight forward.
Thank you
Upon SDK start (after initializing and session start), SDK should report event [CLY]_orientation
with segment mode
providing value of the current device orientation as portrait
or landscape
Then every time orientation changes in the app SDK should report the same event with the same segment and the updated value
This functionality requires events
consent to be available if GDPR consents are enabled.
No other special treatment required, behaves like a regular event
Hello,
I am trying to implement a push notification service for on-premise deployment. Does countly-sdk-web offer that service? I found you mentioning the notification feature but I didn't found it on examples directory. Do you offer notification service for nodejs web app?
Currently, I am not available to cancel the start_event action, just only end_event with sending data to the server.
I want to track how much time the user spending to create a new entity in my application.
The user starts creating an entity, I run start_event
The user ends to create an entity. I run end_event
If the user starts creating and decides to cancel creating and close the feature.
The event will skip. And next time the event time will start again.
The event stays in the array and the next time when the user starts this flow the event time be added to the previously canceled flow
If requests are proxied user agent info is lost so server does not retrieve user agent data from user.
Why can't I count the session duration after initialization? What is the data format? Is it convenient to say? I want to customize data reporting, but I can't count the time。
//initializing countly with params
Countly.init({
app_key: 'key', //your app key
url: 'here', //your server goes here
debug: true
});
Countly.begin_session();
When posting a form, I got the following error: Uncaught TypeError: Converting circular structure to JSON
See the code at the following line
countly-sdk-web/lib/countly.js
Line 1379 in da9e732
You cannot get the attributes from a form like that, see https://html.spec.whatwg.org/multipage/forms.html#dom-form-elements-dev for the defenition.
TL;DR
If you do form[name]
(like form.name
or form.action
) you will get a form control that is using that name
attribute. A small sample: https://codepen.io/joggie/pen/vYKNqYE
Hi,
We would like to send all request in the local storage on beforeunload/unload events. We tried to call repeatly the heartBeat()
until the queue cly_queue
is empty but unsuccessful, Because of the elements in cly_queue are removed only on the reception asynchronously of the counlty's answer.
Is there any way to force the sending of all requests in the local storage manually and quickly?
Thanks
I'm getting the following CORS issue when attempting to run the countly-sdk-web
with Next.js. The error I receive is:
Access to XMLHttpRequest at 'https://countly.doc.ai/i?begin_session=1&metrics=%7B%22_app_version%22%3A%220.0%22%2C%22_ua%22%3A%22Mozilla%2F5.0%20(Macintosh%3B%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F86.0.4240.111%20Safari%2F537.36%22%2C%22_resolution%22%3A%222560x1440%22%2C%22_density%22%3A2%2C%22_locale%22%3A%22en-US%22%7D&app_key=ad952f815d0d64be3fa7c5a39692e7833959e449&device_id=60997e91-16a7-4981-a907-d50e1700b34d&sdk_name=javascript_native_web&sdk_version=20.04×tamp=1603830178200&hour=13&dow=2' from origin 'http://localhost:9000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here is the script I'm running in my _app.jsx
:
<script
type="text/javascript"
dangerouslySetInnerHTML={{
__html: `
Countly.init({
// provide your app key that you retrieved from Countly dashboard
app_key: {app_key_here},
// Provide your server IP or name. Use try.count.ly or us-try.count.ly
// or asia-try.count.ly for EE trial server.
// If you use your own server, make sure you have https enabled if you use
// https below.
url: {url}
});
// track sessions automatically
Countly.track_sessions();
// track pageviews automatically
Countly.track_pageview();
`,
}}
/>
I've tried enabling https://expressjs.com/en/resources/middleware/cors.html middleware in my Next.js app, but I still receive the same error.
Any chance my setup is incorrect?
Thanks for looking into this.
I've seen when running a Lighthouse test on one of my websites that the tracking script provided from Countly is apparently registering an unload listener. This penalizes the score of the website by 7 for Best practices, which could easily be fixed I believe.
From the Lighthouse Page Lifecycle API, they recommend this:
The
unload
event does not fire reliably and listening for it can prevent browser optimizations like the Back-Forward Cache. Consider using thepagehide
orvisibilitychange
events instead.
That would be great to get back to a 100 and follow web standards!
When I try to using this web sdk in my 'Ant Design Pro' project (https://github.com/ant-design/ant-design-pro), and I refer to the React example code. but it looks like can not integrate properly.
I add those code below into src/app.tsx
import Countly from 'countly-sdk-web';
window.Countly = Countly;
Countly.init({
app_key: 'my_appkey',
url: 'http://xxx.xx.xxx.xx'
});
I use npm start and then get the error at Chrome console log ‘Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'init')’
Can some help of this?
On a failed req, countly will loop indefinitely. Should have some number of allowed failures per req!
if(requestQueue.length > 0){
var params = requestQueue.shift();
log("Processing request", params);
sendXmlHttpRequest(params, function(err, params){
log("Request Finished", params, false);
if(err){
requestQueue.unshift(params);
store("cly_queue", requestQueue, true);
}
});
store("cly_queue", requestQueue, true);
}
Responses from server generate a CORS error, I think that's because the method of choice is a GET instead of a POST
I plan to use Countly to provide remote configuration. I also take GDPR consent for analytics. I want to be able to turn on remote config without enabling any analytics.
Currently consent can be recorded for a fine-grained range of analytics collection.
["sessions", "events", "views", "scrolls", "clicks", "forms", "crashes", "attribution", "users", "star-rating", "location", "apm"]
http://countly.github.io/countly-sdk-web/countly.js.html#line103
Consent for remote config does not have a named feature. Instead it is assumed when consent has been added for at least one feature.
http://countly.github.io/countly-sdk-web/countly.js.html#line999
Countly.check_any_consent()
.Countly.group_features({
config: ["unrecognised feature to allow remote config"],
})
Countly.add_consent("config")
I am sending user details via Countly.user_details we are self hosted with Countly Enterprise 14.06.
I don't see these details come thought to the admin portal.
Where should I see them? Or do we need to upgrade
var user = {
"name": venue.name,
"organization": account.businessName,
"custom": {
"venueId": venue.id,
"accountId": account.id,
"state": venue.state,
"postcode": venue.postcode
}
}
Countly.user_details(user);
Debug log
Request Finished
{"user_details":"{\"name\":\"Kahli’s Test Restaurant\",\"organization\":\"Kahli's Test Restaurant\",\"custom\":{\"venueId\":30,\"accountId\":\"bcba31a3-c6ef-40d6-bd1a-f922329774e6\",\"state\":\"NSW\",\"psotcode\":\"2103\"}}","app_key":"2a9b7f95a5fa3c7270a4925495bc83881785b4d0","device_id":"4ea3714c-7aa7-4cce-8c77-ee60d84fd492","timestamp":1441608057,"hour":16,"dow":1}
false
Mark errors as javascript for server
And add optional support for https://github.com/novocaine/sourcemapped-stacktrace through plugins
SDK should be able to record data without device id locally, and then sync it with server when device_id is finally provided
I'd found those code below:
//getting resolution if (screen.width) { var width = (screen.width) ? screen.width : ''; var height = (screen.height) ? screen.height : ''; metrics._resolution = '' + width + "x" + height; }
I found exactly the problem why metrics._resolution return wrong value from ios or android devices:
screen.width/screen.height returns logical resolution(dpi) on iOS while android return physical resolution(pix) on Android:
http://stackoverflow.com/questions/6850164/get-the-device-width-in-javascript
So metrics._resolution should be improved. Cause we developers can't argue the resolution's value with marketing & biz guys. And the boss. So…… I'ts a choice and a compatible problem……
This just took me ages to find. Basically, Countly installs a broken polyfill for Element.closest()
that only uses the element name, not class names. This breaks Element.closest()
, and later attempts to polyfill, because it now has a "valid" function installed, breaking other code down the line.
Using the recommended polyfill on https://developer.mozilla.org/en-US/docs/Web/API/Element/closest would dramatically reduce the risk of breaking apps on IE11 by adding Countly.
I've worked around using (before Countly)...
<script>
if (typeof Element.prototype.closest === 'undefined') {
document.write('<script src="https://cdn.jsdelivr.net/npm/[email protected]/browser.min.js"><\/script>');
}
</script>
Currently, even with the recent CommonJS extension, it's not yet possible to instantiate multiple Countly objects that point to several endpoints. The use-cases for that may be limited, but do exist. It would be very useful if one could eg. write:
var Countly = require('countly-web-sdk');
var countly1 = new Countly(options1);
var countly2 = new Countly(options2);
Alternatively, instantiate only 1, but be able to provide multiple endpoints. I can appreciate that that would probably be a bigger code overhaul with a very limited audience, so I wouldn't really ask for that (although it would solve the problem too of course). Easier for things like GDPR consent (since that should be equal for all instances), but much more internal state to manage I expect.
Please let me know if this is an option for you guys. And if you can't invest the time into this, please do let me know if you would be interested in receiving a PR.
Caveat: I could be very much confused
I've followed https://code.count.ly/integration-web.html and picked jsdelivr
option, which resulted in a blob of javascript that included the following link:
https://cdn.jsdelivr.net/countly-sdk-web/latest/countly.min.js
file size: 18191 bytes
sha512: 54bf53addedf1661ed247702f9ece2867b4d44438737c5a7fb12e4935cbfd0ae589ffa091dbda7237cce7e0ca6cfeccc6388d3e9e9490cf470b301ed99f3778b
I don't know what version that is, but the code is clearly countly.
However, if I go to https://www.jsdelivr.com/package/npm/countly-sdk-web it has this link:
https://cdn.jsdelivr.net/npm/[email protected]/lib/countly.min.js
file size: 34147
sha512: 1c5e334e26b3a330fa24dfab3edf7ba78a5cb401c8a8e8b1c1c9aaa41841fe661420453b1ff65d104bb553385e3cda961442f3c84a6bad0cfbc6a293379947c2
Diff'ing the beautified files, there are quite a lot of differences, for example .passed_data.purpose
which according to git blame is 2 years old with the commit log stating "async load for umd".
html example:
`<a id='aa" href="http://github.com">
The li element was treat as srcElement of the click event. So the id of the link was not tracked.
Those helper methods have the same problem. Please improve:
……
track_clicks
track_links
……
When using the SDK I am getting CORS errors
XMLHttpRequest cannot load
'Access-Control-Allow-Origin' header is present on the requested resource.
Hey Guys , Thanks For Your Analytics System.
I Have a Problem in Web Version . I Use React.js & Next.js With Typescript And I'm Trying to Use WithEffect Sample But I Keep Getting This Error : ReferenceError: Element is not defined at ..\node_modules\countly-sdk-web\lib\countly.js:3190:5
What is This Error About ?
Hi,
I would like to ask you about the support of Countly for multi-page web apps like MVC web app
As I could see in the code, it isn't 100% for a multi-page web app.
For example, we cannot use track_sessions
because everytime we arrive on a page, it will consider to a session. We can call method begin_session
on a page but cannot call method session_duration
or end_session
on other page without calling begin_session
first.
In additional, is there some way to make heartBeat()
public? That we can call it manually instead of waiting for x (ms).
Regards,
I plan to use Countly for user usage data analytics. but when I import an error occurs which causes chrome to display Internal Server Error
and on the chrome console it says Failed to load resource: the server responded with a status of 500 (Internal Server Error)
but in the terminal it says ReferenceError: Element is not defined
this is my code
async componentDidMount() {
let Countly = Countly;
Countly.q = Countly.q;
Countly.app_key = "myAppKey";
Countly.url = "muUrl.Key";
Countly.q.push(["track_sessions"]);
Countly.q.push(["track_pageview"]);
(function() {
let cly = document.createElement("script");
cly.type = "text/javascript";
cly.async = true;
cly.src =
"https://cdnjs.cloudflare.com/ajax/libs/countly-sdk-web/19.2.1/countly.min.js";
cly.onload = function() {
Countly.init();
};
let s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(cly, s);
})();
}
Hi, i am integrating this sdk in react.js but it keeps throwing 400 error saying that App doesn't exist. after a few research i found that the sdk is not sending proper app_key. have a look at the query strings that the sdk send with the request
However i am setting it properly.
I copied the same url that was throwing error and replace the app key with proper app key and send it manually and it worked
Semi-persistent DOM XSS is possible at in sites that use this library. The DOM XSS can be triggered by passing a malicious JSON string/configuration via window.name
to any window.
It is somewhat different from the usual Reflected XSS that you would see. In a normal Reflected XSS, the XSS would likely not work beyond the initial page (i.e. the victim navigated to another page). In this exploit though, the XSS would likely still work.
Note: urls and domains have been changed for security purposes
target.website.com
.target.website.com
loads, you should see an alert(document.cookie)
popup123456.hml content
<p>1. Click 'Open Window' if you are not redirected automatically</p>
<p>2. Once the new page loads finish, you will seen an alert(document.cookie) XSS</p>
<input type='button' value='open window' onclick='open_window();'>
<script>
function open_window(){
window.name = "cly:" + '{"app_key":"<redacted>","token":"3","purpose":"heatmap","url":"<redacted>/xss 1"}';
window.open("target.website.com",'_self');
}
open_window();
</script>
This effect persists past page refresh.
I believe the issue originates around here
https://github.com/Countly/countly-sdk-web/blob/master/lib/countly.js#L321
https://github.com/Countly/countly-sdk-web/blob/master/lib/countly.js#L344
Hi There,
This project is still using an old implementation of LGTM's automated code review, which has now been disabled. To continue using automated code review, and receive checks on your Pull Requests, please install the GitHub App on this repository.
Thanks,
The LGTM Team
Hi, I'm trying out Countly and has a local setup running. When trying out the web tracking I noticed the dashboard showed a new user and session everytime a refreshed the page. The device id in local storage also got a new value every time.
When debugging the code it turned out the stored device id (plain string) could not be parsed by JSON.parse. The exceptions is caught which sets the data to null. The result is a newly generated device id.
countly-sdk-web/lib/countly.js
Line 2155 in d5effb8
Looking at the history i guess it worked earlier because you didn't set the data to null in the catch clause.
I didn't find any other issue about this but it should be really critical?
When completing the feedback form and sending it successfully, I can see the ratings on server, but not the comments or the emails.
Hi Guys,
I use countly-sdk-web
in my nextjs react
project, and cause ssr
mode i think, when i use yarn add countly-sdk-web
and import Countly from 'countly-sdk-web'
it throw a error, so i find the countly.min.js
out and add it to the script
append to dom
, then i init it:
Countly.q = [];
Countly.app_key = 'my app key';
Countly.url = 'my api url';
Countly.init();
there is a new case: i need detect how long a user views a list item, in that case, i need commit the list item info to countly
, the valid items of course, that means in custom event
, the segmentation
may like this, and include user's info as well:
<div
onClick={
() => {
const { Countly } = window;
const obj = {
user: {
id: 1,
createTime: 2,
mobile: 3
},
listItem: [
{
a: 1,
b: 2
},
{
c: 3,
d: 4
}
],
other1: 'other1',
other2: 'other2'
};
for (const k in obj) {
const ele = obj[k];
obj[k] = JSON.stringify(ele);
}
Countly.q.push(['add_event', {
'key': 'next-project-list-item-observe',
'segmentation': obj
}]);
console.log(obj);
}
}
>press me</div>
console.log
statement output is expected:
{
listItem: '[{"a":1,"b":2},{"c":3,"d":4}]',
other1: '"other1"',
other2: '"other2"',
user: '{"id":1,"createTime":2,"mobile":3}'
}
the api interface returns success as well, but in the management platform, the listItem
and user
segmentation is No data
:
other1
and other2
are go well of course, i check the network
find the result returns well:
in the earlier time, a tried sth like this:
'segmentation': {
'a': '{a: 1, b: 2}'
}
'segmentation': {
'b': '"{a: 1, b: 2}"'
}
'segmentation': {
'c': JSON.stringify({a:1, b:2})
}
and
'segmentation': {
'd': {a:1, b:2}
}
and check these in the management platform, it confused a lot:
{a. 1, b. 2}
"{a. 1, b. 2}"
, seriously??How could be a dot 1
?The api results are returned as expected i can see in the above, but how??And as u can see, in segmentation c
, i used JSON.stringify
, but the result shown in the management is No data
...
So is there a way to send a json string to the countly
use segmentation
?Or another way can do it?
thanks
countly-web-sdk currently has a different package.json version than the published version, causing npm outdated
to gripe:
╰─ ✔ ❯ npm outdated
Package Current Wanted Latest Location Depended by
@esbuild/linux-x64 MISSING 0.16.17 0.16.17 - ignite-metrics
countly-sdk-web 22.06.4 22.6.4 22.6.4 node_modules/countly-sdk-web ignite-metrics
see
I made a PR with a fix proposal here: #55
Hey Countly Team, thanks for making this great product.
I have noticed a bug in my application with the Countly library, steps to reproduce:
localStorage
on one of the tabs, like localStorage.removeItem('cly_event')
cannot read property 'length' of null
I traced this down to a line in the Countly SDK:
if (eventQueue.length > 0) {
I noticed that another section of the Countly SDK listens to changes on localStorage
, and tries to update them when they change:
window.addEventListener('storage', function(e) {
var key = e.key + "";
switch(key) {
//queue of requests
case Countly.namespace + "cly_queue":
requestQueue = Countly.deserialize(e.newValue);
break;
//queue of events
case Countly.namespace + "cly_event":
eventQueue = Countly.deserialize(e.newValue);
break;
case Countly.namespace + "cly_remote_configs":
remoteConfigs = Countly.deserialize(e.newValue);
break;
case Countly.namespace + "cly_ignore":
Countly.ignore_visitor = Countly.deserialize(e.newValue);
break;
case Countly.namespace + "cly_id":
Countly.device_id = Countly.deserialize(e.newValue);
break;
default:
// do nothing
}
});
So, for example, if we call localStorage.removeItem('cly_event')
, the above code will be run and the new value of eventQueue
will be null
.
Then, when eventQueue.length
is called, an error will be thrown.
I discovered the issue when running Cypress tests. Cypress clears lots of state-ish things between tests, and sometimes it does that just after the application has loaded, causing this error.
From reading the code, it seems to me like you never really want these values to be null
, even if they are null
in localStorage
.
What do you think of this PR? Also, if this can be merged, how can I get the change into the minified file? Are there any tests you need written?
Thanks!
Reason: This would help in attracting more contributors. As it would be easy to understand the code and identify the issues/improvements.
Note: I can contribute in the migration. I did something related to it, splitting into multiple files (Also migrating to Typescript) and now it is working as it should. And it can be further improved for better readability.
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.