@yqg/multiple-click
Version:
Monitor user's multiple click behavior and report
156 lines (155 loc) • 7.1 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.processTrackingConfig = void 0;
const constant_1 = require("./constant");
const type_1 = require("./type");
const utils_1 = require("./utils");
const getTrackingUrl = ({ env }) => {
let trackingHost;
if (env === type_1.ENV_TYPE.PROD_INDO) {
trackingHost = constant_1.EVENT_TRACKING_HOST_PROD_INDO;
}
else if (env.startsWith('prod')) {
trackingHost = constant_1.EVENT_TRACKING_HOST_PROD;
}
else if (env !== type_1.ENV_TYPE.DEV) {
trackingHost = constant_1.EVENT_TRACKING_HOST_TEST;
}
const trackingUrl = trackingHost ? `${trackingHost}/logMetrics` : null;
return trackingUrl;
};
const fetchRemoteConfig = ({ appId, env }) => {
const configCenterHost = constant_1.CONFIG_CENTER_HOST_MAP[env];
if (!configCenterHost) {
return Promise.resolve({});
}
const configUrl = `${configCenterHost}/api-web/hostCond?app=web-multiple-click&prefix=${appId}`;
return fetch(configUrl)
.then((res) => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b;
const data = (_b = (_a = (yield res.json())) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b[appId];
const config = data ? JSON.parse(data) : {};
return (0, utils_1.pick)(config, ['disabled', 'interval', 'continuousCount', 'range', 'excludeRules']);
}))
.catch(() => ({}));
};
const uploadTrackingInfoFactory = (config) => {
const { appId, appVersion, customTrackingInfo } = config;
const trackingUrl = getTrackingUrl(config);
const osType = (0, utils_1.getOsType)();
const headers = {
Country: (0, utils_1.getCountry)(),
'YQG-PLATFORM-SDK-TYPE': appId,
'CONTENT-TYPE': 'application/json;charset=UTF-8'
};
const extraInfoGetter = ({ target: _target }) => {
const target = _target;
const { outerHTML } = target;
const { x: clientLeft, y: clientTop } = target.getBoundingClientRect();
return {
url: location.href,
outerHTML: outerHTML.slice(0, constant_1.OUTER_HTML_MAX_LENGTH),
selector: (0, utils_1.htmlTreeAsString)(target),
offsetTop: clientTop + window.scrollY,
offsetLeft: clientLeft + window.scrollX,
clientTop,
clientLeft
};
};
const uploadTrackingInfo = (event) => {
const trackingInfo = customTrackingInfo(event, extraInfoGetter(event));
if (!trackingUrl) {
console.info('无需上报多次点击事件,事件信息:', trackingInfo);
return;
}
const info = {
level: 'INFO',
logs: [
{
appId,
appVersion: appVersion || null,
osType,
measurement: 'app_metrics_for_multiple_click',
metricsType: 'metricsType1',
time: Date.now().toString(),
message: 'multiple click',
parameter: trackingInfo
}
]
};
fetch(trackingUrl, { method: 'post', headers, body: JSON.stringify(info) }).catch(err => console.error('多次点击上报异常', err));
};
return uploadTrackingInfo;
};
const processTrackingConfig = (config) => __awaiter(void 0, void 0, void 0, function* () {
const _a = yield fetchRemoteConfig(config), { disabled } = _a, remoteConfig = __rest(_a, ["disabled"]);
if (disabled) {
return null;
}
const defaultConfig = {
interval: constant_1.DEFAULT_TRIGGER_INTERVAL,
continuousCount: constant_1.DEFAULT_TRIGGER_CONTINUOUS_COUNT,
range: constant_1.DEFAULT_TRIGGER_RANGE,
customTrackingInfo: (_, extra) => extra,
filter: () => false
};
const mergedConfig = Object.assign(Object.assign(Object.assign(Object.assign({}, defaultConfig), config), remoteConfig), { excludeRules: [...(0, utils_1.castArray)(config.excludeRules || []), ...(0, utils_1.castArray)(remoteConfig.excludeRules || [])] });
const { appId, appVersion, env, interval, continuousCount, range, customTrackingInfo, filter, excludeRules } = mergedConfig;
if (typeof appId !== 'string' || !appId) {
throw new Error('appId需为非空字符串');
}
if (appVersion && typeof appVersion !== 'string') {
throw new Error('appVersion需为字符串');
}
const envTypeList = Object.values(type_1.ENV_TYPE);
if (!envTypeList.includes(env)) {
throw new Error(`env需为${envTypeList.join('、')}中的一个`);
}
if (typeof interval !== 'number' || interval <= 0) {
throw new Error('interval需为大于0的数字');
}
if (typeof continuousCount !== 'number' || continuousCount <= 1) {
throw new Error('continuousCount需为大于1的数字');
}
if (typeof range !== 'number' || range <= 0) {
throw new Error('range需为大于0的数字');
}
if (typeof customTrackingInfo !== 'function') {
throw new Error('customTrackingInfo需为函数');
}
if (typeof filter !== 'function') {
throw new Error('filter需为函数');
}
const validatedConfig = Object.assign(Object.assign({}, config), { interval,
continuousCount,
range,
customTrackingInfo,
filter });
const uploadTrackingInfo = uploadTrackingInfoFactory(validatedConfig);
const parsedExcludeRules = excludeRules.map((_a) => {
var { page } = _a, rule = __rest(_a, ["page"]);
return (Object.assign(Object.assign({}, rule), { page: page ? (0, utils_1.castArray)(page) : [] }));
});
return { interval, continuousCount, range, uploadTrackingInfo, filter, excludeRules: parsedExcludeRules };
});
exports.processTrackingConfig = processTrackingConfig;