UNPKG

posthog-js

Version:

Posthog-js allows you to automatically capture usage and send events to PostHog.

293 lines • 13.2 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Heatmaps = void 0; var rageclick_1 = __importDefault(require("./extensions/rageclick")); var globals_1 = require("@posthog/browser-common/utils/globals"); var autocapture_utils_1 = require("@posthog/browser-common/utils/autocapture-utils"); var constants_1 = require("./constants"); var core_1 = require("@posthog/core"); var logger_1 = require("@posthog/browser-common/utils/logger"); var element_utils_1 = require("@posthog/browser-common/utils/element-utils"); var dead_clicks_autocapture_1 = require("./extensions/dead-clicks-autocapture"); var core_2 = require("@posthog/core"); var general_utils_1 = require("@posthog/browser-common/utils/general-utils"); var request_utils_1 = require("@posthog/browser-common/utils/request-utils"); var event_utils_1 = require("@posthog/browser-common/utils/event-utils"); var DEFAULT_FLUSH_INTERVAL = 5000; var logger = (0, logger_1.createLogger)('[Heatmaps]'); function elementOrParentPositionMatches(el, matches, breakOnElement) { var _a, _b, _c; var curEl = el; while (curEl && (0, element_utils_1.isElementNode)(curEl) && !(0, element_utils_1.isTag)(curEl, 'body')) { if (curEl === breakOnElement) { return false; } var position = void 0; try { position = (_c = ((_b = (_a = curEl.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) !== null && _b !== void 0 ? _b : globals_1.window)) === null || _c === void 0 ? void 0 : _c.getComputedStyle(curEl).position; } catch (_d) { return false; } if ((0, core_2.includes)(matches, position)) { return true; } curEl = (0, autocapture_utils_1.getParentElement)(curEl); } return false; } function isValidMouseEvent(e) { return (0, core_1.isObject)(e) && 'clientX' in e && 'clientY' in e && (0, core_1.isNumber)(e.clientX) && (0, core_1.isNumber)(e.clientY); } function shouldPoll(document) { return (document === null || document === void 0 ? void 0 : document.visibilityState) === 'visible'; } var Heatmaps = /** @class */ (function () { function Heatmaps(instance) { var _a; this._enabledServerSide = false; this._initialized = false; this._flushInterval = null; this.instance = instance; this._enabledServerSide = !!((_a = this.instance.persistence) === null || _a === void 0 ? void 0 : _a.props[constants_1.HEATMAPS_ENABLED_SERVER_SIDE]); this.rageclicks = new rageclick_1.default(instance.config.rageclick); } Object.defineProperty(Heatmaps.prototype, "_config", { get: function () { return this.instance.config; }, enumerable: false, configurable: true }); Heatmaps.prototype.initialize = function () { this.startIfEnabled(); }; Object.defineProperty(Heatmaps.prototype, "flushIntervalMilliseconds", { get: function () { var flushInterval = DEFAULT_FLUSH_INTERVAL; if ((0, core_1.isObject)(this._config.capture_heatmaps) && this._config.capture_heatmaps.flush_interval_milliseconds) { flushInterval = this._config.capture_heatmaps.flush_interval_milliseconds; } return flushInterval; }, enumerable: false, configurable: true }); Object.defineProperty(Heatmaps.prototype, "isEnabled", { get: function () { if (!(0, core_1.isNullish)(this._config.capture_heatmaps)) { return this._config.capture_heatmaps !== false; } if (!(0, core_1.isNullish)(this._config.enable_heatmaps)) { return this._config.enable_heatmaps; } return this._enabledServerSide; }, enumerable: false, configurable: true }); Heatmaps.prototype.startIfEnabled = function () { var _a; if (this.isEnabled) { // nested if here since we only want to run the else // if this.enabled === false // not if this method is called more than once if (this._initialized) { return; } logger.info('starting...'); this._setupListeners(); this._onVisibilityChange(); } else { clearInterval((_a = this._flushInterval) !== null && _a !== void 0 ? _a : undefined); this._removeListeners(); this.getAndClearBuffer(); } }; Heatmaps.prototype.onRemoteConfig = function (result) { var _a; if (!result.ok) { // Failure behaves like a response without a heatmaps key. return; } var response = result.config; if (!('heatmaps' in response)) { return; } var optIn = !!response['heatmaps']; if (this.instance.persistence) { this.instance.persistence.register((_a = {}, _a[constants_1.HEATMAPS_ENABLED_SERVER_SIDE] = optIn, _a)); } // store this in-memory in case persistence is disabled this._enabledServerSide = optIn; this.startIfEnabled(); }; Heatmaps.prototype.getAndClearBuffer = function () { var buffer = this._buffer; this._buffer = undefined; return buffer; }; Heatmaps.prototype._onDeadClick = function (click) { // heatmaps only plots click coordinates; this also rejects swipe candidates (never // expected on this path), since a swipe's TouchEvent has no clientX/clientY if (!isValidMouseEvent(click.originalEvent)) { return; } this._onClick(click.originalEvent, 'deadclick'); }; Heatmaps.prototype._onVisibilityChange = function () { // always clear the interval just in case if (this._flushInterval) { clearInterval(this._flushInterval); } this._flushInterval = shouldPoll(globals_1.document) ? setInterval(this._flush.bind(this), this.flushIntervalMilliseconds) : null; }; Heatmaps.prototype._setupListeners = function () { var _this = this; if (!globals_1.window || !globals_1.document) { return; } this._flushHandler = this._flush.bind(this); (0, general_utils_1.addEventListener)(globals_1.window, constants_1.DOM_EVENT_BEFOREUNLOAD, this._flushHandler); this._onClickHandler = function (e) { return _this._onClick((e || (globals_1.window === null || globals_1.window === void 0 ? void 0 : globals_1.window.event))); }; (0, general_utils_1.addEventListener)(globals_1.document, 'click', this._onClickHandler, { capture: true }); this._onMouseMoveHandler = function (e) { return _this._onMouseMove((e || (globals_1.window === null || globals_1.window === void 0 ? void 0 : globals_1.window.event))); }; (0, general_utils_1.addEventListener)(globals_1.document, 'mousemove', this._onMouseMoveHandler, { capture: true }); this._deadClicksCapture = new dead_clicks_autocapture_1.DeadClicksAutocapture(this.instance, dead_clicks_autocapture_1.isDeadClicksEnabledForHeatmaps, this._onDeadClick.bind(this)); this._deadClicksCapture.startIfEnabledOrStop(); this._onVisibilityChange_handler = this._onVisibilityChange.bind(this); (0, general_utils_1.addEventListener)(globals_1.document, constants_1.DOM_EVENT_VISIBILITYCHANGE, this._onVisibilityChange_handler); this._initialized = true; }; Heatmaps.prototype._removeListeners = function () { var _a; if (!globals_1.window || !globals_1.document) { return; } if (this._flushHandler) { globals_1.window.removeEventListener(constants_1.DOM_EVENT_BEFOREUNLOAD, this._flushHandler); } if (this._onClickHandler) { globals_1.document.removeEventListener('click', this._onClickHandler, { capture: true }); } if (this._onMouseMoveHandler) { globals_1.document.removeEventListener('mousemove', this._onMouseMoveHandler, { capture: true }); } if (this._onVisibilityChange_handler) { globals_1.document.removeEventListener(constants_1.DOM_EVENT_VISIBILITYCHANGE, this._onVisibilityChange_handler); } clearTimeout(this._mouseMoveTimeout); (_a = this._deadClicksCapture) === null || _a === void 0 ? void 0 : _a.stop(); this._initialized = false; }; Heatmaps.prototype._getProperties = function (e, type) { // We need to know if the target element is fixed or not // If fixed then we won't account for scrolling // If not then we will account for scrolling var scrollY = this.instance.scrollManager.scrollY(); var scrollX = this.instance.scrollManager.scrollX(); var scrollElement = this.instance.scrollManager.scrollElement(); var isFixedOrSticky = elementOrParentPositionMatches((0, autocapture_utils_1.getEventTarget)(e), ['fixed', 'sticky'], scrollElement); return { x: e.clientX + (isFixedOrSticky ? 0 : scrollX), y: e.clientY + (isFixedOrSticky ? 0 : scrollY), target_fixed: isFixedOrSticky, type: type, }; }; Heatmaps.prototype._onClick = function (e, type) { var _a; if (type === void 0) { type = 'click'; } if ((0, element_utils_1.isElementInToolbar)(e.target) || !isValidMouseEvent(e)) { return; } var properties = this._getProperties(e, type); if (((_a = this.rageclicks) === null || _a === void 0 ? void 0 : _a.isRageClick(e.clientX, e.clientY, new Date().getTime())) && (0, autocapture_utils_1.shouldCaptureRageclick)((0, autocapture_utils_1.getEventTarget)(e), this.instance.config.rageclick)) { this._capture(__assign(__assign({}, properties), { type: 'rageclick' })); } this._capture(properties); }; Heatmaps.prototype._onMouseMove = function (e) { var _this = this; if ((0, element_utils_1.isElementInToolbar)(e.target) || !isValidMouseEvent(e)) { return; } clearTimeout(this._mouseMoveTimeout); this._mouseMoveTimeout = setTimeout(function () { _this._capture(_this._getProperties(e, 'mousemove')); }, 500); }; Heatmaps.prototype._capture = function (properties) { if (!globals_1.window) { return; } var href = this._config.disable_capture_url_hashes ? (0, core_1.stripUrlHash)(globals_1.window.location.href) : globals_1.window.location.href; // mask url query params var maskPersonalDataProperties = this._config.mask_personal_data_properties; var customPersonalDataProperties = this._config.custom_personal_data_properties; var paramsToMask = maskPersonalDataProperties ? __spreadArray(__spreadArray([], __read(event_utils_1.PERSONAL_DATA_CAMPAIGN_PARAMS), false), __read((customPersonalDataProperties || [])), false) : []; var url = (0, request_utils_1.maskQueryParams)(href, paramsToMask, event_utils_1.MASKED); this._buffer = this._buffer || {}; if (!this._buffer[url]) { this._buffer[url] = []; } this._buffer[url].push(properties); }; Heatmaps.prototype._flush = function () { if (!this._buffer || (0, core_1.isEmptyObject)(this._buffer)) { return; } this.instance.capture('$$heatmap', { $heatmap_data: this.getAndClearBuffer(), }); }; return Heatmaps; }()); exports.Heatmaps = Heatmaps; //# sourceMappingURL=heatmaps.js.map