Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

analytics-client

Package Overview
Dependencies
Maintainers
1
Versions
145
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

analytics-client - npm Package Compare versions

Comparing version 0.1.0-roman-url-params-c6b3a1ce20618c2b4dbb9082e6aeac10598a5796 to 0.1.0

dist/index.js

1

CHANGELOG.md

@@ -9,2 +9,3 @@ # Change Log

* Avoid calling mixpanel in constructor [Roman Mazur]
* Add URL query string tools [Roman Mazur]

11

dist/src/url-params.d.ts
import { Mixpanel } from 'mixpanel-browser';
export declare class AnalyticsUrlParams {
private mixpanel?;
private readonly cookiesSupported;
private deviceIds;
constructor(mixpanel?: Mixpanel | undefined);
private storeInboundDeviceIds;
private retrieveAndMerge;
private takeFirstId;
static clearCookies(): void;
private setDeviceIds;
clearCookies(): void;
consumeUrlParameters(queryString: string): string | null;
allDeviceIds(): string;
deviceIdQuery(): string;
allDeviceIds(): string[];
getDeviceIdsQueryString(): string;
}
{
"name": "analytics-client",
"version": "0.1.0-roman-url-params-c6b3a1ce20618c2b4dbb9082e6aeac10598a5796",
"version": "0.1.0",
"description": "Convenient builders to compose analytics tools",

@@ -16,3 +16,3 @@ "repository": {

"lint": "resin-lint --typescript src/ test/ && tsc --noEmit",
"build": "npm run test && webpack",
"build": "npm run test && tsc && webpack",
"prepublish": "npm run build"

@@ -22,3 +22,2 @@ },

"@analytics/cookie-utils": "^0.2.2",
"lodash": "^4.17.15",
"typescript": "^3.6.3"

@@ -30,3 +29,5 @@ },

"@types/mixpanel-browser": "^2.23.1",
"husky": "^3.0.9",
"jest": "^24.9.0",
"lint-staged": "^9.4.2",
"mixpanel-browser": "^2.29.1",

@@ -38,3 +39,19 @@ "resin-lint": "^3.1.0",

"webpack-cli": "^3.3.9"
},
"lint-staged": {
"*.ts": [
"prettier --config ./node_modules/resin-lint/config/.prettierrc --write",
"resin-lint --typescript --no-prettier",
"git add"
],
"test/**/*.ts": [
"resin-lint --typescript --no-prettier --tests"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"pre-push": "npm run lint"
}
}
}
Analytics client
================
Client side analytics tools.
Client part of analytics services used at balena.

@@ -23,3 +23,3 @@ ## Installation

const signupUrl = '/signup?' + analytics.deviceIdQuery();
const signupUrl = '/signup?' + analytics.getDeviceIdsQueryString();
```

@@ -1,6 +0,5 @@

import * as _ from 'lodash';
import {
getCookie,
hasCookieSupport,
setCookie,
hasCookieSupport,
} from '@analytics/cookie-utils';

@@ -14,4 +13,2 @@ import { Mixpanel } from 'mixpanel-browser';

const cookiesSupported = hasCookieSupport();
/**

@@ -22,31 +19,29 @@ * AnalyticsUrlParams helps with handling analytics-related URL parameters

export class AnalyticsUrlParams {
private deviceIds: string | null;
private readonly cookiesSupported = hasCookieSupport();
private deviceIds: Set<string> = new Set();
constructor(private mixpanel?: Mixpanel) {}
constructor(private mixpanel?: Mixpanel) {
const storedValue = this.cookiesSupported
? getCookie(COOKIES_DEVICE_IDS)
: null;
this.setDeviceIds(storedValue, null);
}
private storeInboundDeviceIds(ids: string, currentDeviceId: string | null) {
const list = ids ? ids.split(deviceIdSeparator) : [];
private setDeviceIds(
inputIdString: string | null,
currentDeviceId: string | null,
) {
const list = inputIdString ? inputIdString.split(deviceIdSeparator) : [];
if (currentDeviceId) {
list.push(currentDeviceId);
}
const res = this.retrieveAndMerge(list);
this.deviceIds = res;
if (cookiesSupported) {
setCookie(COOKIES_DEVICE_IDS, res);
this.deviceIds = new Set(list.concat(Array.from(this.deviceIds)));
if (this.cookiesSupported) {
setCookie(COOKIES_DEVICE_IDS, Array.from(this.deviceIds).join(','));
}
return res;
return list.length > 0 ? list[0] : null;
}
private retrieveAndMerge(input: string[]) {
const storedValue = cookiesSupported ? getCookie(COOKIES_DEVICE_IDS) : null;
const storedList = storedValue ? storedValue.split(deviceIdSeparator) : [];
return _.union(storedList, input).join(',');
}
private takeFirstId(passedId: string) {
return passedId.split(deviceIdSeparator, 1)[0];
}
static clearCookies() {
if (cookiesSupported) {
clearCookies() {
if (this.cookiesSupported) {
setCookie(COOKIES_DEVICE_IDS, '');

@@ -68,19 +63,20 @@ }

if (passedDeviceId) {
let originalMpId: string | null = null;
const originalMixpanelId =
this.mixpanel != null ? this.mixpanel.get_distinct_id() : null;
if (this.mixpanel != null) {
originalMpId = this.mixpanel.get_distinct_id();
const newCurrentDeviceId = this.setDeviceIds(
passedDeviceId,
originalMixpanelId,
);
if (this.mixpanel != null && newCurrentDeviceId) {
// Switch mixpanel ID to using the passed device ID, so we can track events in one timeline branch.
// Previous user activity recorded with another device ID will be merged upon signup,
// since we store the previous ID to pass it to other sites.
const mpId = this.takeFirstId(passedDeviceId);
this.mixpanel.register({
distinct_id: mpId,
$device_id: mpId,
distinct_id: newCurrentDeviceId,
$device_id: newCurrentDeviceId,
});
}
this.storeInboundDeviceIds(passedDeviceId, originalMpId);
params.delete(URL_PARAM_DEVICE_ID);

@@ -94,10 +90,12 @@ return params.toString();

/**
* @return all anonymous device IDs that can be passed to other sites, separated with comma
* @return all anonymous device IDs that can be passed to other sites
*/
allDeviceIds(): string {
if (this.deviceIds == null) {
const knownIds = this.mixpanel == null ? [] : [ this.mixpanel.get_distinct_id() ];
this.deviceIds = this.retrieveAndMerge(knownIds);
allDeviceIds() {
const mixpanelId = this.mixpanel ? this.mixpanel.get_distinct_id() : null;
if (mixpanelId == null) {
return Array.from(this.deviceIds);
}
return this.deviceIds!;
const res = new Set(this.deviceIds);
res.add(mixpanelId);
return Array.from(res);
}

@@ -108,9 +106,9 @@

*/
deviceIdQuery(): string {
getDeviceIdsQueryString(): string {
const ids = this.allDeviceIds();
if (ids === '') {
if (ids.length === 0) {
return '';
}
return `${URL_PARAM_DEVICE_ID}=${encodeURIComponent(ids)}`;
return `${URL_PARAM_DEVICE_ID}=${encodeURIComponent(ids.join(','))}`;
}
}
import { Mixpanel } from 'mixpanel-browser';
import { AnalyticsUrlParams } from '../src/url-params';
beforeEach(AnalyticsUrlParams.clearCookies);
beforeEach(() => new AnalyticsUrlParams().clearCookies());

@@ -29,4 +29,6 @@ test('remove device ID from query string', () => {

const urlParams = new AnalyticsUrlParams();
urlParams.consumeUrlParameters('d_id=' + encodeURIComponent('d1,d2,d3') + '&other=value');
expect(urlParams.allDeviceIds()).toBe('d1,d2,d3');
urlParams.consumeUrlParameters(
'd_id=' + encodeURIComponent('d1,d2,d3') + '&other=value',
);
expect(urlParams.allDeviceIds()).toStrictEqual(['d1', 'd2', 'd3']);
});

@@ -36,6 +38,8 @@

const urlParams = new AnalyticsUrlParams();
expect(urlParams.deviceIdQuery()).toBe('');
expect(urlParams.getDeviceIdsQueryString()).toBe('');
urlParams.consumeUrlParameters('d_id=d1,d2,d3&other=value');
expect(urlParams.deviceIdQuery()).toBe('d_id=' + encodeURIComponent('d1,d2,d3'));
expect(urlParams.getDeviceIdsQueryString()).toBe(
'd_id=' + encodeURIComponent('d1,d2,d3'),
);
});

@@ -51,2 +55,3 @@

registerParams: any;
distinctIdRetrieved: boolean;
}

@@ -57,4 +62,8 @@

registerParams: null,
distinctIdRetrieved: false,
get_distinct_id: () => 'test_mp_distinct_id',
get_distinct_id() {
this.distinctIdRetrieved = true;
return 'test_mp_distinct_id';
},
register(params: any) {

@@ -81,2 +90,7 @@ this.registerParams = params;

test("don't call mixpanel in constructor", () => {
const [, mock] = mpUrlParameters();
expect(mock.distinctIdRetrieved).toBeFalsy();
});
test('update mixpanel state', () => {

@@ -110,5 +124,10 @@ const [urlParams, mp] = mpUrlParameters();

const [urlParams] = mpUrlParameters();
expect(urlParams.allDeviceIds()).toBe('test_mp_distinct_id');
expect(urlParams.allDeviceIds()).toStrictEqual(['test_mp_distinct_id']);
urlParams.consumeUrlParameters('d_id=d1,d2,d3&other=value');
expect(urlParams.allDeviceIds()).toBe('d1,d2,d3,test_mp_distinct_id');
expect(urlParams.allDeviceIds()).toStrictEqual([
'd1',
'd2',
'd3',
'test_mp_distinct_id',
]);
});

@@ -119,9 +138,14 @@

new AnalyticsUrlParams().consumeUrlParameters('d_id=2');
expect(new AnalyticsUrlParams().allDeviceIds()).toBe('1,2');
expect(new AnalyticsUrlParams().allDeviceIds()).toContain('1');
expect(new AnalyticsUrlParams().allDeviceIds()).toContain('2');
});
test('encodes URI component', () => {
new AnalyticsUrlParams().consumeUrlParameters('d_id=' + encodeURIComponent('%%$!!'));
expect(new AnalyticsUrlParams().allDeviceIds()).toBe('%%$!!');
expect(new AnalyticsUrlParams().deviceIdQuery()).toBe('d_id=%25%25%24!!');
new AnalyticsUrlParams().consumeUrlParameters(
'd_id=' + encodeURIComponent('%%$!!'),
);
expect(new AnalyticsUrlParams().allDeviceIds()).toStrictEqual(['%%$!!']);
expect(new AnalyticsUrlParams().getDeviceIdsQueryString()).toBe(
'd_id=%25%25%24!!',
);
});

@@ -21,3 +21,5 @@ const path = require('path');

path: path.resolve(__dirname, 'dist'),
libraryTarget: 'var',
library: 'analyticsClient'
}
};

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc