@workleap/mixpanel 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/createTrackingFunction.d.ts +37 -0
- package/dist/createTrackingFunction.js +44 -0
- package/dist/createTrackingFunction.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/properties.d.ts +13 -0
- package/dist/properties.js +39 -0
- package/dist/properties.js.map +1 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +127 -0
- package/dist/utils.js.map +1 -0
- package/package.json +49 -0
- package/src/createTrackingFunction.ts +65 -0
- package/src/index.ts +2 -0
- package/src/properties.ts +36 -0
- package/src/utils.ts +135 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type TrackEventProperties } from "./properties.ts";
|
|
2
|
+
export interface TrackingOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Whether to keep the connection alive for the tracking request.
|
|
5
|
+
* It is mostly used for tracking links where the user might navigate away before the request is completed.
|
|
6
|
+
*
|
|
7
|
+
* Caution! The body size for keepalive requests is limited to 64 kibibytes.
|
|
8
|
+
*
|
|
9
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#keepalive
|
|
10
|
+
*
|
|
11
|
+
* @default false
|
|
12
|
+
*/
|
|
13
|
+
keepAlive?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A function that sends tracking events to the tracking API.
|
|
17
|
+
* @param eventName The name of the event to track.
|
|
18
|
+
* @param properties The properties to send with the event.
|
|
19
|
+
* @param options Options for tracking the event.
|
|
20
|
+
*/
|
|
21
|
+
export type TrackingFunction = (eventName: string, properties: TrackEventProperties, options?: TrackingOptions) => Promise<void>;
|
|
22
|
+
interface CreateTrackingFunctionOptions {
|
|
23
|
+
/**
|
|
24
|
+
* The product identifier of the target product.
|
|
25
|
+
* @default null
|
|
26
|
+
*/
|
|
27
|
+
targetProductId?: string | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates a function that sends tracking events to the tracking API.
|
|
31
|
+
* @param productId Your product identifier. e.g. "wlp", "ov"
|
|
32
|
+
* @param trackingApiUrl The base URL of the tracking controlled. e.g. "/api/navigation"
|
|
33
|
+
* @param createOptions Options for creating the tracking function.
|
|
34
|
+
* @returns A function that sends tracking events to the tracking API.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createTrackingFunction(productId: string, trackingApiBaseUrl: string, createOptions?: CreateTrackingFunctionOptions): TrackingFunction;
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as __WEBPACK_EXTERNAL_MODULE__properties_js_2cf909bd__ from "./properties.js";
|
|
2
|
+
|
|
3
|
+
;// CONCATENATED MODULE: external "./properties.js"
|
|
4
|
+
|
|
5
|
+
;// CONCATENATED MODULE: ./src/createTrackingFunction.ts?__rslib_entry__
|
|
6
|
+
|
|
7
|
+
// Cannot use URL() because it doesn't support relative base url: https://github.com/whatwg/url/issues/531.
|
|
8
|
+
function resolveApiUrl(path, baseUrl) {
|
|
9
|
+
return `${baseUrl}${baseUrl.endsWith("/") ? "" : "/"}${path.startsWith("/") ? path.substring(1) : path}`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates a function that sends tracking events to the tracking API.
|
|
13
|
+
* @param productId Your product identifier. e.g. "wlp", "ov"
|
|
14
|
+
* @param trackingApiUrl The base URL of the tracking controlled. e.g. "/api/navigation"
|
|
15
|
+
* @param createOptions Options for creating the tracking function.
|
|
16
|
+
* @returns A function that sends tracking events to the tracking API.
|
|
17
|
+
*/ function createTrackingFunction(productId, trackingApiBaseUrl, createOptions = {}) {
|
|
18
|
+
const targetProductId = createOptions?.targetProductId ?? null;
|
|
19
|
+
return async (eventName, properties, options)=>{
|
|
20
|
+
const baseProperties = (0,__WEBPACK_EXTERNAL_MODULE__properties_js_2cf909bd__.getBaseProperties)();
|
|
21
|
+
const allProperties = {
|
|
22
|
+
...baseProperties,
|
|
23
|
+
...properties
|
|
24
|
+
};
|
|
25
|
+
await fetch(resolveApiUrl("tracking/track", trackingApiBaseUrl), {
|
|
26
|
+
method: "POST",
|
|
27
|
+
credentials: "include",
|
|
28
|
+
keepalive: options?.keepAlive,
|
|
29
|
+
headers: {
|
|
30
|
+
"Content-Type": "application/json"
|
|
31
|
+
},
|
|
32
|
+
body: JSON.stringify({
|
|
33
|
+
eventName,
|
|
34
|
+
productId,
|
|
35
|
+
targetProductId: targetProductId,
|
|
36
|
+
properties: allProperties
|
|
37
|
+
})
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { createTrackingFunction };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=createTrackingFunction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createTrackingFunction.js","sources":["webpack://@workleap/mixpanel/./src/createTrackingFunction.ts"],"sourcesContent":["import { getBaseProperties, type TrackEventProperties } from \"./properties.ts\";\n\nexport interface TrackingOptions {\n /**\n * Whether to keep the connection alive for the tracking request.\n * It is mostly used for tracking links where the user might navigate away before the request is completed.\n *\n * Caution! The body size for keepalive requests is limited to 64 kibibytes.\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#keepalive\n *\n * @default false\n */\n keepAlive?: boolean;\n}\n\n/**\n * A function that sends tracking events to the tracking API.\n * @param eventName The name of the event to track.\n * @param properties The properties to send with the event.\n * @param options Options for tracking the event.\n */\nexport type TrackingFunction = (eventName: string, properties: TrackEventProperties, options?: TrackingOptions) => Promise<void>;\n\n// Cannot use URL() because it doesn't support relative base url: https://github.com/whatwg/url/issues/531.\nfunction resolveApiUrl(path: string, baseUrl: string | undefined) : string {\n return `${baseUrl}${baseUrl!.endsWith(\"/\") ? \"\" : \"/\"}${path.startsWith(\"/\") ? path.substring(1) : path}`;\n}\n\ninterface CreateTrackingFunctionOptions {\n /**\n * The product identifier of the target product.\n * @default null\n */\n targetProductId?: string | null;\n}\n\n/**\n * Creates a function that sends tracking events to the tracking API.\n * @param productId Your product identifier. e.g. \"wlp\", \"ov\"\n * @param trackingApiUrl The base URL of the tracking controlled. e.g. \"/api/navigation\"\n * @param createOptions Options for creating the tracking function.\n * @returns A function that sends tracking events to the tracking API.\n */\nexport function createTrackingFunction(productId: string, trackingApiBaseUrl: string, createOptions: CreateTrackingFunctionOptions = {}) : TrackingFunction {\n const targetProductId = createOptions?.targetProductId ?? null;\n\n return async (eventName, properties, options) => {\n const baseProperties = getBaseProperties();\n const allProperties = { ...baseProperties, ...properties };\n\n await fetch(resolveApiUrl(\"tracking/track\", trackingApiBaseUrl), {\n method: \"POST\",\n credentials: \"include\",\n keepalive: options?.keepAlive,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n eventName,\n productId,\n targetProductId: targetProductId,\n properties: allProperties\n })\n });\n };\n}\n"],"names":["getBaseProperties","resolveApiUrl","path","baseUrl","createTrackingFunction","productId","trackingApiBaseUrl","createOptions","targetProductId","eventName","properties","options","baseProperties","allProperties","fetch","JSON"],"mappings":";;;;;AAA+E;AAwB/E,2GAA2G;AAC3G,SAASC,cAAcC,IAAY,EAAEC,OAA2B;IAC5D,OAAO,GAAGA,UAAUA,QAAS,QAAQ,CAAC,OAAO,KAAK,MAAMD,KAAK,UAAU,CAAC,OAAOA,KAAK,SAAS,CAAC,KAAKA,MAAM;AAC7G;AAUA;;;;;;CAMC,GACM,SAASE,uBAAuBC,SAAiB,EAAEC,kBAA0B,EAAEC,gBAA+C,CAAC,CAAC;IACnI,MAAMC,kBAAkBD,eAAe,mBAAmB;IAE1D,OAAO,OAAOE,WAAWC,YAAYC;QACjC,MAAMC,iBAAiBZ,yEAAiBA;QACxC,MAAMa,gBAAgB;YAAE,GAAGD,cAAc;YAAE,GAAGF,UAAU;QAAC;QAEzD,MAAMI,MAAMb,cAAc,kBAAkBK,qBAAqB;YAC7D,QAAQ;YACR,aAAa;YACb,WAAWK,SAAS;YACpB,SAAS;gBAAE,gBAAgB;YAAmB;YAC9C,MAAMI,KAAK,SAAS,CAAC;gBACjBN;gBACAJ;gBACA,iBAAiBG;gBACjB,YAAYK;YAChB;QACJ;IACJ;AACJ"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./createTrackingFunction.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["webpack://@workleap/mixpanel/./src/index.ts"],"sourcesContent":["export * from \"./createTrackingFunction.ts\";\n\n"],"names":[],"mappings":";;;AAA4C"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type TrackEventProperties = Record<string, unknown>;
|
|
2
|
+
export declare function getBaseProperties(): {
|
|
3
|
+
$os: string;
|
|
4
|
+
$browser: string;
|
|
5
|
+
$referrer: string;
|
|
6
|
+
$referring_domain: string;
|
|
7
|
+
$device: string;
|
|
8
|
+
$current_url: string;
|
|
9
|
+
$browser_version: number | null;
|
|
10
|
+
$screen_height: number;
|
|
11
|
+
$screen_width: number;
|
|
12
|
+
IsMobile: boolean;
|
|
13
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as __WEBPACK_EXTERNAL_MODULE__utils_js_d88b7fe1__ from "./utils.js";
|
|
2
|
+
|
|
3
|
+
;// CONCATENATED MODULE: external "./utils.js"
|
|
4
|
+
|
|
5
|
+
;// CONCATENATED MODULE: ./src/properties.ts?__rslib_entry__
|
|
6
|
+
|
|
7
|
+
const BaseTrackingProperties = {
|
|
8
|
+
AppVersion: "AppVersion",
|
|
9
|
+
Browser: "$browser",
|
|
10
|
+
BrowserVersion: "$browser_version",
|
|
11
|
+
CurrentUrl: "$current_url",
|
|
12
|
+
Device: "$device",
|
|
13
|
+
IsMobile: "IsMobile",
|
|
14
|
+
Os: "$os",
|
|
15
|
+
Referrer: "$referrer",
|
|
16
|
+
ReferringDomain: "$referring_domain",
|
|
17
|
+
ScreenHeight: "$screen_height",
|
|
18
|
+
ScreenWidth: "$screen_width"
|
|
19
|
+
};
|
|
20
|
+
function getBaseProperties() {
|
|
21
|
+
const userAgent = navigator.userAgent;
|
|
22
|
+
const device = (0,__WEBPACK_EXTERNAL_MODULE__utils_js_d88b7fe1__.deviceType)(userAgent);
|
|
23
|
+
return {
|
|
24
|
+
[BaseTrackingProperties.Os]: (0,__WEBPACK_EXTERNAL_MODULE__utils_js_d88b7fe1__.osName)(userAgent),
|
|
25
|
+
[BaseTrackingProperties.Browser]: (0,__WEBPACK_EXTERNAL_MODULE__utils_js_d88b7fe1__.browserName)(userAgent, navigator.vendor),
|
|
26
|
+
[BaseTrackingProperties.Referrer]: document.referrer,
|
|
27
|
+
[BaseTrackingProperties.ReferringDomain]: (0,__WEBPACK_EXTERNAL_MODULE__utils_js_d88b7fe1__.referringDomain)(document.referrer),
|
|
28
|
+
[BaseTrackingProperties.Device]: device,
|
|
29
|
+
[BaseTrackingProperties.CurrentUrl]: window.location.href,
|
|
30
|
+
[BaseTrackingProperties.BrowserVersion]: (0,__WEBPACK_EXTERNAL_MODULE__utils_js_d88b7fe1__.browserVersion)(userAgent, navigator.vendor),
|
|
31
|
+
[BaseTrackingProperties.ScreenHeight]: window.screen.height,
|
|
32
|
+
[BaseTrackingProperties.ScreenWidth]: window.screen.width,
|
|
33
|
+
[BaseTrackingProperties.IsMobile]: device.length > 0
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { getBaseProperties };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=properties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"properties.js","sources":["webpack://@workleap/mixpanel/./src/properties.ts"],"sourcesContent":["\nimport { browserName, browserVersion, deviceType, osName, referringDomain } from \"./utils.ts\";\n\nexport type TrackEventProperties = Record<string, unknown>;\n\nconst BaseTrackingProperties = {\n AppVersion: \"AppVersion\",\n Browser: \"$browser\",\n BrowserVersion: \"$browser_version\",\n CurrentUrl: \"$current_url\",\n Device: \"$device\",\n IsMobile: \"IsMobile\",\n Os: \"$os\",\n Referrer: \"$referrer\",\n ReferringDomain: \"$referring_domain\",\n ScreenHeight: \"$screen_height\",\n ScreenWidth: \"$screen_width\"\n} as const;\n\nexport function getBaseProperties() {\n const userAgent = navigator.userAgent;\n const device = deviceType(userAgent);\n\n return {\n [BaseTrackingProperties.Os]: osName(userAgent),\n [BaseTrackingProperties.Browser]: browserName(userAgent, navigator.vendor),\n [BaseTrackingProperties.Referrer]: document.referrer,\n [BaseTrackingProperties.ReferringDomain]: referringDomain(document.referrer),\n [BaseTrackingProperties.Device]: device,\n [BaseTrackingProperties.CurrentUrl]: window.location.href,\n [BaseTrackingProperties.BrowserVersion]: browserVersion(userAgent, navigator.vendor),\n [BaseTrackingProperties.ScreenHeight]: window.screen.height,\n [BaseTrackingProperties.ScreenWidth]: window.screen.width,\n [BaseTrackingProperties.IsMobile]: device.length > 0\n } satisfies TrackEventProperties;\n}\n"],"names":["browserName","browserVersion","deviceType","osName","referringDomain","BaseTrackingProperties","getBaseProperties","userAgent","navigator","device","document","window"],"mappings":";;;;;AAC8F;AAI9F,MAAMK,yBAAyB;IAC3B,YAAY;IACZ,SAAS;IACT,gBAAgB;IAChB,YAAY;IACZ,QAAQ;IACR,UAAU;IACV,IAAI;IACJ,UAAU;IACV,iBAAiB;IACjB,cAAc;IACd,aAAa;AACjB;AAEO,SAASC;IACZ,MAAMC,YAAYC,UAAU,SAAS;IACrC,MAAMC,SAASP,6DAAUA,CAACK;IAE1B,OAAO;QACH,CAACF,uBAAuB,EAAE,CAAC,EAAEF,yDAAMA,CAACI;QACpC,CAACF,uBAAuB,OAAO,CAAC,EAAEL,8DAAWA,CAACO,WAAWC,UAAU,MAAM;QACzE,CAACH,uBAAuB,QAAQ,CAAC,EAAEK,SAAS,QAAQ;QACpD,CAACL,uBAAuB,eAAe,CAAC,EAAED,kEAAeA,CAACM,SAAS,QAAQ;QAC3E,CAACL,uBAAuB,MAAM,CAAC,EAAEI;QACjC,CAACJ,uBAAuB,UAAU,CAAC,EAAEM,OAAO,QAAQ,CAAC,IAAI;QACzD,CAACN,uBAAuB,cAAc,CAAC,EAAEJ,iEAAcA,CAACM,WAAWC,UAAU,MAAM;QACnF,CAACH,uBAAuB,YAAY,CAAC,EAAEM,OAAO,MAAM,CAAC,MAAM;QAC3D,CAACN,uBAAuB,WAAW,CAAC,EAAEM,OAAO,MAAM,CAAC,KAAK;QACzD,CAACN,uBAAuB,QAAQ,CAAC,EAAEI,OAAO,MAAM,GAAG;IACvD;AACJ"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare function browserName(userAgent: string, vendor?: string, opera?: object): "" | "Opera Mini" | "Opera" | "BlackBerry" | "Internet Explorer Mobile" | "Microsoft Edge" | "Facebook Mobile" | "Chrome" | "Chrome iOS" | "UC Browser" | "Firefox iOS" | "Mobile Safari" | "Safari" | "Android Mobile" | "Konqueror" | "Firefox" | "Internet Explorer" | "Mozilla";
|
|
2
|
+
/**
|
|
3
|
+
* This function detects which browser version is running this script,
|
|
4
|
+
* parsing major and minor version (e.g., 42.1). User agent strings from:
|
|
5
|
+
* http://www.useragentstring.com/pages/useragentstring.php
|
|
6
|
+
*/
|
|
7
|
+
export declare function browserVersion(userAgent: string, vendor?: string, opera?: object): number | null;
|
|
8
|
+
export declare function osName(userAgent: string): "" | "BlackBerry" | "Android" | "Windows Phone" | "Windows" | "iOS" | "Mac OS X" | "Linux" | "Chrome OS";
|
|
9
|
+
export declare function deviceType(userAgent: string): "" | "BlackBerry" | "Android" | "Windows Phone" | "iPad" | "iPod Touch" | "iPhone";
|
|
10
|
+
export declare function referringDomain(referrer: string): string;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
|
|
2
|
+
;// CONCATENATED MODULE: ./src/utils.ts?__rslib_entry__
|
|
3
|
+
// This code is adapted from https://github.com/mixpanel/mixpanel-js/blob/master/src/utils.js
|
|
4
|
+
function browserName(userAgent, vendor, opera) {
|
|
5
|
+
// vendor is undefined for at least IE9
|
|
6
|
+
vendor = vendor || ""; // eslint-disable-line no-param-reassign
|
|
7
|
+
if (opera || userAgent.includes(" OPR/")) {
|
|
8
|
+
if (userAgent.includes("Mini")) {
|
|
9
|
+
return "Opera Mini";
|
|
10
|
+
}
|
|
11
|
+
return "Opera";
|
|
12
|
+
} else if (/(BlackBerry|PlayBook|BB10)/i.test(userAgent)) {
|
|
13
|
+
return "BlackBerry";
|
|
14
|
+
} else if (userAgent.includes("IEMobile") || userAgent.includes("WPDesktop")) {
|
|
15
|
+
return "Internet Explorer Mobile";
|
|
16
|
+
} else if (userAgent.includes("Edge")) {
|
|
17
|
+
return "Microsoft Edge";
|
|
18
|
+
} else if (userAgent.includes("FBIOS")) {
|
|
19
|
+
return "Facebook Mobile";
|
|
20
|
+
} else if (userAgent.includes("Chrome")) {
|
|
21
|
+
return "Chrome";
|
|
22
|
+
} else if (userAgent.includes("CriOS")) {
|
|
23
|
+
return "Chrome iOS";
|
|
24
|
+
} else if (userAgent.includes("UCWEB") || userAgent.includes("UCBrowser")) {
|
|
25
|
+
return "UC Browser";
|
|
26
|
+
} else if (userAgent.includes("FxiOS")) {
|
|
27
|
+
return "Firefox iOS";
|
|
28
|
+
} else if (vendor.includes("Apple")) {
|
|
29
|
+
if (userAgent.includes("Mobile")) {
|
|
30
|
+
return "Mobile Safari";
|
|
31
|
+
}
|
|
32
|
+
return "Safari";
|
|
33
|
+
} else if (userAgent.includes("Android")) {
|
|
34
|
+
return "Android Mobile";
|
|
35
|
+
} else if (userAgent.includes("Konqueror")) {
|
|
36
|
+
return "Konqueror";
|
|
37
|
+
} else if (userAgent.includes("Firefox")) {
|
|
38
|
+
return "Firefox";
|
|
39
|
+
} else if (userAgent.includes("MSIE") || userAgent.includes("Trident/")) {
|
|
40
|
+
return "Internet Explorer";
|
|
41
|
+
} else if (userAgent.includes("Gecko")) {
|
|
42
|
+
return "Mozilla";
|
|
43
|
+
}
|
|
44
|
+
return "";
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* This function detects which browser version is running this script,
|
|
48
|
+
* parsing major and minor version (e.g., 42.1). User agent strings from:
|
|
49
|
+
* http://www.useragentstring.com/pages/useragentstring.php
|
|
50
|
+
*/ function browserVersion(userAgent, vendor, opera) {
|
|
51
|
+
const browser = browserName(userAgent, vendor, opera);
|
|
52
|
+
const versionRegexs = {
|
|
53
|
+
"Internet Explorer Mobile": /rv:(\d+(\.\d+)?)/,
|
|
54
|
+
"Microsoft Edge": /Edge\/(\d+(\.\d+)?)/,
|
|
55
|
+
"Chrome": /Chrome\/(\d+(\.\d+)?)/,
|
|
56
|
+
"Chrome iOS": /CriOS\/(\d+(\.\d+)?)/,
|
|
57
|
+
"UC Browser": /(UCBrowser|UCWEB)\/(\d+(\.\d+)?)/,
|
|
58
|
+
"Safari": /Version\/(\d+(\.\d+)?)/,
|
|
59
|
+
"Mobile Safari": /Version\/(\d+(\.\d+)?)/,
|
|
60
|
+
"Opera": /(Opera|OPR)\/(\d+(\.\d+)?)/,
|
|
61
|
+
"Firefox": /Firefox\/(\d+(\.\d+)?)/,
|
|
62
|
+
"Firefox iOS": /FxiOS\/(\d+(\.\d+)?)/,
|
|
63
|
+
"Konqueror": /Konqueror:(\d+(\.\d+)?)/,
|
|
64
|
+
"BlackBerry": /BlackBerry (\d+(\.\d+)?)/,
|
|
65
|
+
"Android Mobile": /android\s(\d+(\.\d+)?)/,
|
|
66
|
+
"Internet Explorer": /(rv:|MSIE )(\d+(\.\d+)?)/,
|
|
67
|
+
"Mozilla": /rv:(\d+(\.\d+)?)/
|
|
68
|
+
};
|
|
69
|
+
const regex = versionRegexs[browser];
|
|
70
|
+
if (regex === undefined) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const matches = userAgent.match(regex);
|
|
74
|
+
if (!matches) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
return parseFloat(matches[matches.length - 2]);
|
|
78
|
+
}
|
|
79
|
+
function osName(userAgent) {
|
|
80
|
+
const a = userAgent;
|
|
81
|
+
if (/Windows/i.test(a)) {
|
|
82
|
+
if (/Phone/.test(a) || /WPDesktop/.test(a)) {
|
|
83
|
+
return "Windows Phone";
|
|
84
|
+
}
|
|
85
|
+
return "Windows";
|
|
86
|
+
} else if (/(iPhone|iPad|iPod)/.test(a)) {
|
|
87
|
+
return "iOS";
|
|
88
|
+
} else if (/Android/.test(a)) {
|
|
89
|
+
return "Android";
|
|
90
|
+
} else if (/(BlackBerry|PlayBook|BB10)/i.test(a)) {
|
|
91
|
+
return "BlackBerry";
|
|
92
|
+
} else if (/Mac/i.test(a)) {
|
|
93
|
+
return "Mac OS X";
|
|
94
|
+
} else if (/Linux/.test(a)) {
|
|
95
|
+
return "Linux";
|
|
96
|
+
} else if (/CrOS/.test(a)) {
|
|
97
|
+
return "Chrome OS";
|
|
98
|
+
}
|
|
99
|
+
return "";
|
|
100
|
+
}
|
|
101
|
+
function deviceType(userAgent) {
|
|
102
|
+
if (/Windows Phone/i.test(userAgent) || /WPDesktop/.test(userAgent)) {
|
|
103
|
+
return "Windows Phone";
|
|
104
|
+
} else if (/iPad/.test(userAgent)) {
|
|
105
|
+
return "iPad";
|
|
106
|
+
} else if (/iPod/.test(userAgent)) {
|
|
107
|
+
return "iPod Touch";
|
|
108
|
+
} else if (/iPhone/.test(userAgent)) {
|
|
109
|
+
return "iPhone";
|
|
110
|
+
} else if (/(BlackBerry|PlayBook|BB10)/i.test(userAgent)) {
|
|
111
|
+
return "BlackBerry";
|
|
112
|
+
} else if (/Android/.test(userAgent)) {
|
|
113
|
+
return "Android";
|
|
114
|
+
}
|
|
115
|
+
return "";
|
|
116
|
+
}
|
|
117
|
+
function referringDomain(referrer) {
|
|
118
|
+
const split = referrer.split("/");
|
|
119
|
+
if (split.length >= 3) {
|
|
120
|
+
return split[2];
|
|
121
|
+
}
|
|
122
|
+
return "";
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export { browserName, browserVersion, deviceType, osName, referringDomain };
|
|
126
|
+
|
|
127
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["webpack://@workleap/mixpanel/./src/utils.ts"],"sourcesContent":["// This code is adapted from https://github.com/mixpanel/mixpanel-js/blob/master/src/utils.js\nexport function browserName(userAgent: string, vendor?: string, opera?: object) {\n // vendor is undefined for at least IE9\n vendor = vendor || \"\"; // eslint-disable-line no-param-reassign\n\n if (opera || userAgent.includes(\" OPR/\")) {\n if (userAgent.includes(\"Mini\")) {\n return \"Opera Mini\";\n }\n\n return \"Opera\";\n } else if (/(BlackBerry|PlayBook|BB10)/i.test(userAgent)) {\n return \"BlackBerry\";\n } else if (userAgent.includes(\"IEMobile\") || userAgent.includes(\"WPDesktop\")) {\n return \"Internet Explorer Mobile\";\n } else if (userAgent.includes(\"Edge\")) {\n return \"Microsoft Edge\";\n } else if (userAgent.includes(\"FBIOS\")) {\n return \"Facebook Mobile\";\n } else if (userAgent.includes(\"Chrome\")) {\n return \"Chrome\";\n } else if (userAgent.includes(\"CriOS\")) {\n return \"Chrome iOS\";\n } else if (userAgent.includes(\"UCWEB\") || userAgent.includes(\"UCBrowser\")) {\n return \"UC Browser\";\n } else if (userAgent.includes(\"FxiOS\")) {\n return \"Firefox iOS\";\n } else if (vendor.includes(\"Apple\")) {\n if (userAgent.includes(\"Mobile\")) {\n return \"Mobile Safari\";\n }\n\n return \"Safari\";\n } else if (userAgent.includes(\"Android\")) {\n return \"Android Mobile\";\n } else if (userAgent.includes(\"Konqueror\")) {\n return \"Konqueror\";\n } else if (userAgent.includes(\"Firefox\")) {\n return \"Firefox\";\n } else if (userAgent.includes(\"MSIE\") || userAgent.includes(\"Trident/\")) {\n return \"Internet Explorer\";\n } else if (userAgent.includes(\"Gecko\")) {\n return \"Mozilla\";\n }\n\n return \"\";\n}\n\n/**\n * This function detects which browser version is running this script,\n * parsing major and minor version (e.g., 42.1). User agent strings from:\n * http://www.useragentstring.com/pages/useragentstring.php\n */\nexport function browserVersion(userAgent: string, vendor?: string, opera?: object) {\n const browser = browserName(userAgent, vendor, opera);\n const versionRegexs: { [key: string]: RegExp } = {\n \"Internet Explorer Mobile\": /rv:(\\d+(\\.\\d+)?)/,\n \"Microsoft Edge\": /Edge\\/(\\d+(\\.\\d+)?)/,\n \"Chrome\": /Chrome\\/(\\d+(\\.\\d+)?)/,\n \"Chrome iOS\": /CriOS\\/(\\d+(\\.\\d+)?)/,\n \"UC Browser\": /(UCBrowser|UCWEB)\\/(\\d+(\\.\\d+)?)/,\n \"Safari\": /Version\\/(\\d+(\\.\\d+)?)/,\n \"Mobile Safari\": /Version\\/(\\d+(\\.\\d+)?)/,\n \"Opera\": /(Opera|OPR)\\/(\\d+(\\.\\d+)?)/,\n \"Firefox\": /Firefox\\/(\\d+(\\.\\d+)?)/,\n \"Firefox iOS\": /FxiOS\\/(\\d+(\\.\\d+)?)/,\n \"Konqueror\": /Konqueror:(\\d+(\\.\\d+)?)/,\n \"BlackBerry\": /BlackBerry (\\d+(\\.\\d+)?)/,\n \"Android Mobile\": /android\\s(\\d+(\\.\\d+)?)/,\n \"Internet Explorer\": /(rv:|MSIE )(\\d+(\\.\\d+)?)/,\n \"Mozilla\": /rv:(\\d+(\\.\\d+)?)/\n };\n const regex = versionRegexs[browser];\n if (regex === undefined) {\n return null;\n }\n const matches = userAgent.match(regex);\n if (!matches) {\n return null;\n }\n\n return parseFloat(matches[matches.length - 2]);\n}\n\nexport function osName(userAgent: string) {\n const a = userAgent;\n if (/Windows/i.test(a)) {\n if (/Phone/.test(a) || /WPDesktop/.test(a)) {\n return \"Windows Phone\";\n }\n\n return \"Windows\";\n } else if (/(iPhone|iPad|iPod)/.test(a)) {\n return \"iOS\";\n } else if (/Android/.test(a)) {\n return \"Android\";\n } else if (/(BlackBerry|PlayBook|BB10)/i.test(a)) {\n return \"BlackBerry\";\n } else if (/Mac/i.test(a)) {\n return \"Mac OS X\";\n } else if (/Linux/.test(a)) {\n return \"Linux\";\n } else if (/CrOS/.test(a)) {\n return \"Chrome OS\";\n }\n\n return \"\";\n}\n\nexport function deviceType(userAgent: string) {\n if (/Windows Phone/i.test(userAgent) || /WPDesktop/.test(userAgent)) {\n return \"Windows Phone\";\n } else if (/iPad/.test(userAgent)) {\n return \"iPad\";\n } else if (/iPod/.test(userAgent)) {\n return \"iPod Touch\";\n } else if (/iPhone/.test(userAgent)) {\n return \"iPhone\";\n } else if (/(BlackBerry|PlayBook|BB10)/i.test(userAgent)) {\n return \"BlackBerry\";\n } else if (/Android/.test(userAgent)) {\n return \"Android\";\n }\n\n return \"\";\n}\n\nexport function referringDomain(referrer: string) {\n const split = referrer.split(\"/\");\n if (split.length >= 3) {\n return split[2];\n }\n\n return \"\";\n}\n"],"names":["browserName","userAgent","vendor","opera","browserVersion","browser","versionRegexs","regex","undefined","matches","parseFloat","osName","a","deviceType","referringDomain","referrer","split"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@workleap/mixpanel",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/workleap/wl-tracking.git",
|
|
8
|
+
"directory": "packages/mixpanel"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public",
|
|
12
|
+
"provenance": true
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"src",
|
|
24
|
+
"dist",
|
|
25
|
+
"CHANGELOG.md",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@rsbuild/core": "1.2.19",
|
|
30
|
+
"@rslib/core": "0.5.5",
|
|
31
|
+
"@workleap/eslint-plugin": "3.3.1",
|
|
32
|
+
"@workleap/rslib-configs": "1.0.3",
|
|
33
|
+
"@workleap/typescript-configs": "3.0.2",
|
|
34
|
+
"eslint": "8.57.1",
|
|
35
|
+
"happy-dom": "17.4.4",
|
|
36
|
+
"typescript": "5.8.2",
|
|
37
|
+
"vitest": "3.0.9"
|
|
38
|
+
},
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18.0.0"
|
|
41
|
+
},
|
|
42
|
+
"sideEffects": false,
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "rslib build --config ./rslib.build.ts",
|
|
45
|
+
"eslint": "eslint . --max-warnings=-0 --cache --cache-location node_modules/.cache/eslint",
|
|
46
|
+
"typecheck": "tsc",
|
|
47
|
+
"test": "vitest --config vitest.config.ts --no-watch"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { getBaseProperties, type TrackEventProperties } from "./properties.ts";
|
|
2
|
+
|
|
3
|
+
export interface TrackingOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Whether to keep the connection alive for the tracking request.
|
|
6
|
+
* It is mostly used for tracking links where the user might navigate away before the request is completed.
|
|
7
|
+
*
|
|
8
|
+
* Caution! The body size for keepalive requests is limited to 64 kibibytes.
|
|
9
|
+
*
|
|
10
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#keepalive
|
|
11
|
+
*
|
|
12
|
+
* @default false
|
|
13
|
+
*/
|
|
14
|
+
keepAlive?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A function that sends tracking events to the tracking API.
|
|
19
|
+
* @param eventName The name of the event to track.
|
|
20
|
+
* @param properties The properties to send with the event.
|
|
21
|
+
* @param options Options for tracking the event.
|
|
22
|
+
*/
|
|
23
|
+
export type TrackingFunction = (eventName: string, properties: TrackEventProperties, options?: TrackingOptions) => Promise<void>;
|
|
24
|
+
|
|
25
|
+
// Cannot use URL() because it doesn't support relative base url: https://github.com/whatwg/url/issues/531.
|
|
26
|
+
function resolveApiUrl(path: string, baseUrl: string | undefined) : string {
|
|
27
|
+
return `${baseUrl}${baseUrl!.endsWith("/") ? "" : "/"}${path.startsWith("/") ? path.substring(1) : path}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface CreateTrackingFunctionOptions {
|
|
31
|
+
/**
|
|
32
|
+
* The product identifier of the target product.
|
|
33
|
+
* @default null
|
|
34
|
+
*/
|
|
35
|
+
targetProductId?: string | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Creates a function that sends tracking events to the tracking API.
|
|
40
|
+
* @param productId Your product identifier. e.g. "wlp", "ov"
|
|
41
|
+
* @param trackingApiUrl The base URL of the tracking controlled. e.g. "/api/navigation"
|
|
42
|
+
* @param createOptions Options for creating the tracking function.
|
|
43
|
+
* @returns A function that sends tracking events to the tracking API.
|
|
44
|
+
*/
|
|
45
|
+
export function createTrackingFunction(productId: string, trackingApiBaseUrl: string, createOptions: CreateTrackingFunctionOptions = {}) : TrackingFunction {
|
|
46
|
+
const targetProductId = createOptions?.targetProductId ?? null;
|
|
47
|
+
|
|
48
|
+
return async (eventName, properties, options) => {
|
|
49
|
+
const baseProperties = getBaseProperties();
|
|
50
|
+
const allProperties = { ...baseProperties, ...properties };
|
|
51
|
+
|
|
52
|
+
await fetch(resolveApiUrl("tracking/track", trackingApiBaseUrl), {
|
|
53
|
+
method: "POST",
|
|
54
|
+
credentials: "include",
|
|
55
|
+
keepalive: options?.keepAlive,
|
|
56
|
+
headers: { "Content-Type": "application/json" },
|
|
57
|
+
body: JSON.stringify({
|
|
58
|
+
eventName,
|
|
59
|
+
productId,
|
|
60
|
+
targetProductId: targetProductId,
|
|
61
|
+
properties: allProperties
|
|
62
|
+
})
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
|
|
2
|
+
import { browserName, browserVersion, deviceType, osName, referringDomain } from "./utils.ts";
|
|
3
|
+
|
|
4
|
+
export type TrackEventProperties = Record<string, unknown>;
|
|
5
|
+
|
|
6
|
+
const BaseTrackingProperties = {
|
|
7
|
+
AppVersion: "AppVersion",
|
|
8
|
+
Browser: "$browser",
|
|
9
|
+
BrowserVersion: "$browser_version",
|
|
10
|
+
CurrentUrl: "$current_url",
|
|
11
|
+
Device: "$device",
|
|
12
|
+
IsMobile: "IsMobile",
|
|
13
|
+
Os: "$os",
|
|
14
|
+
Referrer: "$referrer",
|
|
15
|
+
ReferringDomain: "$referring_domain",
|
|
16
|
+
ScreenHeight: "$screen_height",
|
|
17
|
+
ScreenWidth: "$screen_width"
|
|
18
|
+
} as const;
|
|
19
|
+
|
|
20
|
+
export function getBaseProperties() {
|
|
21
|
+
const userAgent = navigator.userAgent;
|
|
22
|
+
const device = deviceType(userAgent);
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
[BaseTrackingProperties.Os]: osName(userAgent),
|
|
26
|
+
[BaseTrackingProperties.Browser]: browserName(userAgent, navigator.vendor),
|
|
27
|
+
[BaseTrackingProperties.Referrer]: document.referrer,
|
|
28
|
+
[BaseTrackingProperties.ReferringDomain]: referringDomain(document.referrer),
|
|
29
|
+
[BaseTrackingProperties.Device]: device,
|
|
30
|
+
[BaseTrackingProperties.CurrentUrl]: window.location.href,
|
|
31
|
+
[BaseTrackingProperties.BrowserVersion]: browserVersion(userAgent, navigator.vendor),
|
|
32
|
+
[BaseTrackingProperties.ScreenHeight]: window.screen.height,
|
|
33
|
+
[BaseTrackingProperties.ScreenWidth]: window.screen.width,
|
|
34
|
+
[BaseTrackingProperties.IsMobile]: device.length > 0
|
|
35
|
+
} satisfies TrackEventProperties;
|
|
36
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// This code is adapted from https://github.com/mixpanel/mixpanel-js/blob/master/src/utils.js
|
|
2
|
+
export function browserName(userAgent: string, vendor?: string, opera?: object) {
|
|
3
|
+
// vendor is undefined for at least IE9
|
|
4
|
+
vendor = vendor || ""; // eslint-disable-line no-param-reassign
|
|
5
|
+
|
|
6
|
+
if (opera || userAgent.includes(" OPR/")) {
|
|
7
|
+
if (userAgent.includes("Mini")) {
|
|
8
|
+
return "Opera Mini";
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return "Opera";
|
|
12
|
+
} else if (/(BlackBerry|PlayBook|BB10)/i.test(userAgent)) {
|
|
13
|
+
return "BlackBerry";
|
|
14
|
+
} else if (userAgent.includes("IEMobile") || userAgent.includes("WPDesktop")) {
|
|
15
|
+
return "Internet Explorer Mobile";
|
|
16
|
+
} else if (userAgent.includes("Edge")) {
|
|
17
|
+
return "Microsoft Edge";
|
|
18
|
+
} else if (userAgent.includes("FBIOS")) {
|
|
19
|
+
return "Facebook Mobile";
|
|
20
|
+
} else if (userAgent.includes("Chrome")) {
|
|
21
|
+
return "Chrome";
|
|
22
|
+
} else if (userAgent.includes("CriOS")) {
|
|
23
|
+
return "Chrome iOS";
|
|
24
|
+
} else if (userAgent.includes("UCWEB") || userAgent.includes("UCBrowser")) {
|
|
25
|
+
return "UC Browser";
|
|
26
|
+
} else if (userAgent.includes("FxiOS")) {
|
|
27
|
+
return "Firefox iOS";
|
|
28
|
+
} else if (vendor.includes("Apple")) {
|
|
29
|
+
if (userAgent.includes("Mobile")) {
|
|
30
|
+
return "Mobile Safari";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return "Safari";
|
|
34
|
+
} else if (userAgent.includes("Android")) {
|
|
35
|
+
return "Android Mobile";
|
|
36
|
+
} else if (userAgent.includes("Konqueror")) {
|
|
37
|
+
return "Konqueror";
|
|
38
|
+
} else if (userAgent.includes("Firefox")) {
|
|
39
|
+
return "Firefox";
|
|
40
|
+
} else if (userAgent.includes("MSIE") || userAgent.includes("Trident/")) {
|
|
41
|
+
return "Internet Explorer";
|
|
42
|
+
} else if (userAgent.includes("Gecko")) {
|
|
43
|
+
return "Mozilla";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return "";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* This function detects which browser version is running this script,
|
|
51
|
+
* parsing major and minor version (e.g., 42.1). User agent strings from:
|
|
52
|
+
* http://www.useragentstring.com/pages/useragentstring.php
|
|
53
|
+
*/
|
|
54
|
+
export function browserVersion(userAgent: string, vendor?: string, opera?: object) {
|
|
55
|
+
const browser = browserName(userAgent, vendor, opera);
|
|
56
|
+
const versionRegexs: { [key: string]: RegExp } = {
|
|
57
|
+
"Internet Explorer Mobile": /rv:(\d+(\.\d+)?)/,
|
|
58
|
+
"Microsoft Edge": /Edge\/(\d+(\.\d+)?)/,
|
|
59
|
+
"Chrome": /Chrome\/(\d+(\.\d+)?)/,
|
|
60
|
+
"Chrome iOS": /CriOS\/(\d+(\.\d+)?)/,
|
|
61
|
+
"UC Browser": /(UCBrowser|UCWEB)\/(\d+(\.\d+)?)/,
|
|
62
|
+
"Safari": /Version\/(\d+(\.\d+)?)/,
|
|
63
|
+
"Mobile Safari": /Version\/(\d+(\.\d+)?)/,
|
|
64
|
+
"Opera": /(Opera|OPR)\/(\d+(\.\d+)?)/,
|
|
65
|
+
"Firefox": /Firefox\/(\d+(\.\d+)?)/,
|
|
66
|
+
"Firefox iOS": /FxiOS\/(\d+(\.\d+)?)/,
|
|
67
|
+
"Konqueror": /Konqueror:(\d+(\.\d+)?)/,
|
|
68
|
+
"BlackBerry": /BlackBerry (\d+(\.\d+)?)/,
|
|
69
|
+
"Android Mobile": /android\s(\d+(\.\d+)?)/,
|
|
70
|
+
"Internet Explorer": /(rv:|MSIE )(\d+(\.\d+)?)/,
|
|
71
|
+
"Mozilla": /rv:(\d+(\.\d+)?)/
|
|
72
|
+
};
|
|
73
|
+
const regex = versionRegexs[browser];
|
|
74
|
+
if (regex === undefined) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
const matches = userAgent.match(regex);
|
|
78
|
+
if (!matches) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return parseFloat(matches[matches.length - 2]);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function osName(userAgent: string) {
|
|
86
|
+
const a = userAgent;
|
|
87
|
+
if (/Windows/i.test(a)) {
|
|
88
|
+
if (/Phone/.test(a) || /WPDesktop/.test(a)) {
|
|
89
|
+
return "Windows Phone";
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return "Windows";
|
|
93
|
+
} else if (/(iPhone|iPad|iPod)/.test(a)) {
|
|
94
|
+
return "iOS";
|
|
95
|
+
} else if (/Android/.test(a)) {
|
|
96
|
+
return "Android";
|
|
97
|
+
} else if (/(BlackBerry|PlayBook|BB10)/i.test(a)) {
|
|
98
|
+
return "BlackBerry";
|
|
99
|
+
} else if (/Mac/i.test(a)) {
|
|
100
|
+
return "Mac OS X";
|
|
101
|
+
} else if (/Linux/.test(a)) {
|
|
102
|
+
return "Linux";
|
|
103
|
+
} else if (/CrOS/.test(a)) {
|
|
104
|
+
return "Chrome OS";
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return "";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function deviceType(userAgent: string) {
|
|
111
|
+
if (/Windows Phone/i.test(userAgent) || /WPDesktop/.test(userAgent)) {
|
|
112
|
+
return "Windows Phone";
|
|
113
|
+
} else if (/iPad/.test(userAgent)) {
|
|
114
|
+
return "iPad";
|
|
115
|
+
} else if (/iPod/.test(userAgent)) {
|
|
116
|
+
return "iPod Touch";
|
|
117
|
+
} else if (/iPhone/.test(userAgent)) {
|
|
118
|
+
return "iPhone";
|
|
119
|
+
} else if (/(BlackBerry|PlayBook|BB10)/i.test(userAgent)) {
|
|
120
|
+
return "BlackBerry";
|
|
121
|
+
} else if (/Android/.test(userAgent)) {
|
|
122
|
+
return "Android";
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return "";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function referringDomain(referrer: string) {
|
|
129
|
+
const split = referrer.split("/");
|
|
130
|
+
if (split.length >= 3) {
|
|
131
|
+
return split[2];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return "";
|
|
135
|
+
}
|