posthog-js 1.87.3 → 1.87.4

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.
Files changed (64) hide show
  1. package/dist/array.full.js +1 -1
  2. package/dist/array.full.js.map +1 -1
  3. package/dist/array.js +1 -1
  4. package/dist/array.js.map +1 -1
  5. package/dist/es.js +1 -1
  6. package/dist/es.js.map +1 -1
  7. package/dist/exception-autocapture.js +1 -1
  8. package/dist/exception-autocapture.js.map +1 -1
  9. package/dist/module.js +1 -1
  10. package/dist/module.js.map +1 -1
  11. package/lib/package.json +1 -1
  12. package/lib/src/autocapture-utils.js +2 -1
  13. package/lib/src/autocapture-utils.js.map +1 -1
  14. package/lib/src/autocapture.js +2 -1
  15. package/lib/src/autocapture.js.map +1 -1
  16. package/lib/src/decide.js +2 -1
  17. package/lib/src/decide.js.map +1 -1
  18. package/lib/src/extensions/exception-autocapture/index.js +2 -1
  19. package/lib/src/extensions/exception-autocapture/index.js.map +1 -1
  20. package/lib/src/extensions/replay/sessionrecording.js +2 -1
  21. package/lib/src/extensions/replay/sessionrecording.js.map +1 -1
  22. package/lib/src/extensions/replay/web-performance.js +1 -1
  23. package/lib/src/extensions/replay/web-performance.js.map +1 -1
  24. package/lib/src/extensions/segment-integration.d.ts +18 -0
  25. package/lib/src/extensions/segment-integration.js +1 -19
  26. package/lib/src/extensions/segment-integration.js.map +1 -1
  27. package/lib/src/extensions/toolbar.js +3 -1
  28. package/lib/src/extensions/toolbar.js.map +1 -1
  29. package/lib/src/gdpr-utils.js +3 -1
  30. package/lib/src/gdpr-utils.js.map +1 -1
  31. package/lib/src/page-view.js +1 -1
  32. package/lib/src/page-view.js.map +1 -1
  33. package/lib/src/posthog-core.js +4 -2
  34. package/lib/src/posthog-core.js.map +1 -1
  35. package/lib/src/posthog-featureflags.js +2 -1
  36. package/lib/src/posthog-featureflags.js.map +1 -1
  37. package/lib/src/posthog-persistence.js +2 -1
  38. package/lib/src/posthog-persistence.js.map +1 -1
  39. package/lib/src/rate-limiter.js +6 -2
  40. package/lib/src/rate-limiter.js.map +1 -1
  41. package/lib/src/retry-queue.js +1 -1
  42. package/lib/src/retry-queue.js.map +1 -1
  43. package/lib/src/send-request.js +2 -1
  44. package/lib/src/send-request.js.map +1 -1
  45. package/lib/src/sessionid.js +2 -1
  46. package/lib/src/sessionid.js.map +1 -1
  47. package/lib/src/storage.js +2 -1
  48. package/lib/src/storage.js.map +1 -1
  49. package/lib/src/utils/event-utils.js +2 -1
  50. package/lib/src/utils/event-utils.js.map +1 -1
  51. package/lib/src/utils/globals.d.ts +7 -0
  52. package/lib/src/utils/globals.js +12 -0
  53. package/lib/src/utils/globals.js.map +1 -0
  54. package/lib/src/utils/index.d.ts +0 -15
  55. package/lib/src/utils/index.js +2 -87
  56. package/lib/src/utils/index.js.map +1 -1
  57. package/lib/src/utils/logger.d.ts +8 -0
  58. package/lib/src/utils/logger.js +78 -0
  59. package/lib/src/utils/logger.js.map +1 -0
  60. package/lib/src/utils/request-utils.js +2 -1
  61. package/lib/src/utils/request-utils.js.map +1 -1
  62. package/lib/src/uuidv7.js +1 -1
  63. package/lib/src/uuidv7.js.map +1 -1
  64. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"sessionrecording.js","sourceRoot":"","sources":["../../../../src/extensions/replay/sessionrecording.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE,\n SESSION_RECORDING_ENABLED_SERVER_SIDE,\n SESSION_RECORDING_IS_SAMPLED,\n SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE,\n} from '../../constants'\nimport {\n FULL_SNAPSHOT_EVENT_TYPE,\n INCREMENTAL_SNAPSHOT_EVENT_TYPE,\n META_EVENT_TYPE,\n MutationRateLimiter,\n recordOptions,\n rrwebRecord,\n truncateLargeConsoleLogs,\n} from './sessionrecording-utils'\nimport { PostHog } from '../../posthog-core'\nimport { DecideResponse, NetworkRequest, Properties } from '../../types'\nimport { EventType, type eventWithTime, type listenerHandler } from '@rrweb/types'\nimport Config from '../../config'\nimport { _timestamp, loadScript, logger } from '../../utils'\n\nimport { _isBoolean, _isNull, _isNumber, _isObject, _isString, _isUndefined } from '../../utils/type-utils'\n\nconst BASE_ENDPOINT = '/s/'\n\nexport const RECORDING_IDLE_ACTIVITY_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes\nexport const RECORDING_MAX_EVENT_SIZE = 1024 * 1024 * 0.9 // ~1mb (with some wiggle room)\nexport const RECORDING_BUFFER_TIMEOUT = 2000 // 2 seconds\nexport const SESSION_RECORDING_BATCH_KEY = 'recordings'\n\n// NOTE: Importing this type is problematic as we can't safely bundle it to a TS definition so, instead we redefine.\n// import type { record } from 'rrweb2/typings'\n// import type { recordOptions } from 'rrweb/typings/types'\n\n// Copied from rrweb typings to avoid import\nenum IncrementalSource {\n Mutation = 0,\n MouseMove = 1,\n MouseInteraction = 2,\n Scroll = 3,\n ViewportResize = 4,\n Input = 5,\n TouchMove = 6,\n MediaInteraction = 7,\n StyleSheetRule = 8,\n CanvasMutation = 9,\n Font = 10,\n Log = 11,\n Drag = 12,\n StyleDeclaration = 13,\n Selection = 14,\n AdoptedStyleSheet = 15,\n}\n\nconst ACTIVE_SOURCES = [\n IncrementalSource.MouseMove,\n IncrementalSource.MouseInteraction,\n IncrementalSource.Scroll,\n IncrementalSource.ViewportResize,\n IncrementalSource.Input,\n IncrementalSource.TouchMove,\n IncrementalSource.MediaInteraction,\n IncrementalSource.Drag,\n]\n\n/**\n * Session recording starts in buffering mode while waiting for decide response\n * Once the response is received it might be disabled, active or sampled\n * When sampled that means a sample rate is set and the last time the session id was rotated\n * the sample rate determined this session should be sent to the server.\n */\ntype SessionRecordingStatus = 'disabled' | 'sampled' | 'active' | 'buffering'\n\ninterface SnapshotBuffer {\n size: number\n data: any[]\n sessionId: string | null\n windowId: string | null\n}\n\nexport class SessionRecording {\n private _linkedFlagSeen: boolean = false\n private instance: PostHog\n private _endpoint: string\n private windowId: string | null\n private sessionId: string | null\n private _lastActivityTimestamp: number = Date.now()\n private flushBufferTimer?: any\n private buffer?: SnapshotBuffer\n private mutationRateLimiter?: MutationRateLimiter\n private _captureStarted: boolean\n private stopRrweb: listenerHandler | undefined\n private receivedDecide: boolean\n private rrwebRecord: rrwebRecord | undefined\n private isIdle = false\n private _linkedFlag: string | null = null\n private _sampleRate: number | null = null\n private _minimumDuration: number | null = null\n\n public get started(): boolean {\n // TODO could we use status instead of _captureStarted?\n return this._captureStarted\n }\n\n private get sessionManager() {\n if (!this.instance.sessionManager) {\n logger.error('Session recording started without valid sessionManager')\n throw new Error('Session recording started without valid sessionManager. This is a bug.')\n }\n\n return this.instance.sessionManager\n }\n\n private get isSampled(): boolean | null {\n if (_isNumber(this._sampleRate)) {\n return this.instance.get_property(SESSION_RECORDING_IS_SAMPLED)\n } else {\n return null\n }\n }\n\n private get sessionDuration(): number | null {\n const mostRecentSnapshot = this.buffer?.data[this.buffer?.data.length - 1]\n const { sessionStartTimestamp } = this.sessionManager.checkAndGetSessionAndWindowId(true)\n return mostRecentSnapshot ? mostRecentSnapshot.timestamp - sessionStartTimestamp : null\n }\n\n private get isRecordingEnabled() {\n const enabled_server_side = !!this.instance.get_property(SESSION_RECORDING_ENABLED_SERVER_SIDE)\n const enabled_client_side = !this.instance.config.disable_session_recording\n return enabled_server_side && enabled_client_side\n }\n\n private get isConsoleLogCaptureEnabled() {\n const enabled_server_side = !!this.instance.get_property(CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE)\n const enabled_client_side = this.instance.config.enable_recording_console_log\n return enabled_client_side ?? enabled_server_side\n }\n\n private get recordingVersion() {\n const recordingVersion_server_side = this.instance.get_property(SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE)\n const recordingVersion_client_side = this.instance.config.session_recording?.recorderVersion\n return recordingVersion_client_side || recordingVersion_server_side || 'v1'\n }\n\n /**\n * defaults to buffering mode until a decide response is received\n * once a decide response is received status can be disabled, active or sampled\n */\n private get status(): SessionRecordingStatus {\n if (!this.receivedDecide) {\n return 'buffering'\n }\n\n if (!this.isRecordingEnabled) {\n return 'disabled'\n }\n\n if (_isString(this._linkedFlag) && !this._linkedFlagSeen) {\n return 'buffering'\n }\n\n if (_isBoolean(this.isSampled)) {\n return this.isSampled ? 'sampled' : 'disabled'\n } else {\n return 'active'\n }\n }\n\n constructor(instance: PostHog) {\n this.instance = instance\n this._captureStarted = false\n this._endpoint = BASE_ENDPOINT\n this.stopRrweb = undefined\n this.receivedDecide = false\n\n window.addEventListener('beforeunload', () => {\n this._flushBuffer()\n })\n\n if (!this.instance.sessionManager) {\n logger.error('Session recording started without valid sessionManager')\n throw new Error('Session recording started without valid sessionManager. This is a bug.')\n }\n\n const { sessionId, windowId } = this.sessionManager.checkAndGetSessionAndWindowId(true)\n this.windowId = windowId\n this.sessionId = sessionId\n\n this.buffer = this.clearBuffer()\n }\n\n startRecordingIfEnabled() {\n if (this.isRecordingEnabled) {\n this.startCaptureAndTrySendingQueuedSnapshots()\n } else {\n this.stopRecording()\n this.clearBuffer()\n }\n }\n\n stopRecording() {\n if (this._captureStarted && this.stopRrweb) {\n this.stopRrweb()\n this.stopRrweb = undefined\n this._captureStarted = false\n }\n }\n\n private makeSamplingDecision(sessionId: string): void {\n const sessionIdChanged = this.sessionId !== sessionId\n\n if (!_isNumber(this._sampleRate)) {\n this.instance.persistence?.register({\n [SESSION_RECORDING_IS_SAMPLED]: null,\n })\n return\n }\n\n const storedIsSampled = this.isSampled\n\n /**\n * if we get this far then we should make a sampling decision.\n * When the session id changes or there is no stored sampling decision for this session id\n * then we should make a new decision.\n *\n * Otherwise, we should use the stored decision.\n */\n let shouldSample: boolean\n if (sessionIdChanged || !_isBoolean(storedIsSampled)) {\n const randomNumber = Math.random()\n shouldSample = randomNumber < this._sampleRate\n } else {\n shouldSample = storedIsSampled\n }\n\n if (!shouldSample) {\n logger.warn(\n `[SessionSampling] Sample rate (${this._sampleRate}) has determined that this sessionId (${sessionId}) will not be sent to the server.`\n )\n }\n\n this.instance.persistence?.register({\n [SESSION_RECORDING_IS_SAMPLED]: shouldSample,\n })\n }\n\n afterDecideResponse(response: DecideResponse) {\n if (this.instance.persistence) {\n this.instance.persistence.register({\n [SESSION_RECORDING_ENABLED_SERVER_SIDE]: !!response['sessionRecording'],\n [CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE]: response.sessionRecording?.consoleLogRecordingEnabled,\n [SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE]: response.sessionRecording?.recorderVersion,\n })\n }\n\n const receivedSampleRate = response.sessionRecording?.sampleRate\n this._sampleRate =\n _isUndefined(receivedSampleRate) || _isNull(receivedSampleRate) ? null : parseFloat(receivedSampleRate)\n\n const receivedMinimumDuration = response.sessionRecording?.minimumDurationMilliseconds\n this._minimumDuration = _isUndefined(receivedMinimumDuration) ? null : receivedMinimumDuration\n\n this._linkedFlag = response.sessionRecording?.linkedFlag || null\n\n if (response.sessionRecording?.endpoint) {\n this._endpoint = response.sessionRecording?.endpoint\n }\n\n if (_isNumber(this._sampleRate)) {\n this.sessionManager.onSessionId((sessionId) => {\n this.makeSamplingDecision(sessionId)\n })\n }\n\n if (_isString(this._linkedFlag)) {\n const linkedFlag = this._linkedFlag\n this.instance.onFeatureFlags((flags) => {\n this._linkedFlagSeen = flags.includes(linkedFlag)\n })\n }\n\n this.receivedDecide = true\n this.startRecordingIfEnabled()\n }\n\n log(message: string, level: 'log' | 'warn' | 'error' = 'log') {\n this.instance.sessionRecording?.onRRwebEmit({\n type: 6,\n data: {\n plugin: 'rrweb/console@1',\n payload: {\n level,\n trace: [],\n // Even though it is a string we stringify it as that's what rrweb expects\n payload: [JSON.stringify(message)],\n },\n },\n timestamp: _timestamp(),\n })\n }\n\n private startCaptureAndTrySendingQueuedSnapshots() {\n this._startCapture()\n }\n\n private _startCapture() {\n if (_isUndefined(Object.assign)) {\n // According to the rrweb docs, rrweb is not supported on IE11 and below:\n // \"rrweb does not support IE11 and below because it uses the MutationObserver API which was supported by these browsers.\"\n // https://github.com/rrweb-io/rrweb/blob/master/guide.md#compatibility-note\n //\n // However, MutationObserver does exist on IE11, it just doesn't work well and does not detect all changes.\n // Instead, when we load \"recorder.js\", the first JS error is about \"Object.assign\" being undefined.\n // Thus instead of MutationObserver, we look for this function and block recording if it's undefined.\n return\n }\n\n // We do not switch recorder versions midway through a recording.\n if (this._captureStarted || this.instance.config.disable_session_recording) {\n return\n }\n\n this._captureStarted = true\n // We want to ensure the sessionManager is reset if necessary on load of the recorder\n this.sessionManager.checkAndGetSessionAndWindowId()\n\n const recorderJS = this.recordingVersion === 'v2' ? 'recorder-v2.js' : 'recorder.js'\n\n // If recorder.js is already loaded (if array.full.js snippet is used or posthog-js/dist/recorder is\n // imported) or matches the requested recorder version, don't load script. Otherwise, remotely import\n // recorder.js from cdn since it hasn't been loaded.\n if (this.instance.__loaded_recorder_version !== this.recordingVersion) {\n loadScript(this.instance.config.api_host + `/static/${recorderJS}?v=${Config.LIB_VERSION}`, (err) => {\n if (err) {\n return logger.error(`Could not load ${recorderJS}`, err)\n }\n\n this._onScriptLoaded()\n })\n } else {\n this._onScriptLoaded()\n }\n }\n\n private _isInteractiveEvent(event: eventWithTime) {\n return event.type === INCREMENTAL_SNAPSHOT_EVENT_TYPE && ACTIVE_SOURCES.indexOf(event.data?.source) !== -1\n }\n\n private _updateWindowAndSessionIds(event: eventWithTime) {\n // Some recording events are triggered by non-user events (e.g. \"X minutes ago\" text updating on the screen).\n // We don't want to extend the session or trigger a new session in these cases. These events are designated by event\n // type -> incremental update, and source -> mutation.\n\n const isUserInteraction = this._isInteractiveEvent(event)\n\n if (!isUserInteraction && !this.isIdle) {\n // We check if the lastActivityTimestamp is old enough to go idle\n if (event.timestamp - this._lastActivityTimestamp > RECORDING_IDLE_ACTIVITY_TIMEOUT_MS) {\n this.isIdle = true\n }\n }\n\n if (isUserInteraction) {\n this._lastActivityTimestamp = event.timestamp\n if (this.isIdle) {\n // Remove the idle state if set and trigger a full snapshot as we will have ignored previous mutations\n this.isIdle = false\n this._tryTakeFullSnapshot()\n }\n }\n\n if (this.isIdle) {\n return\n }\n\n // We only want to extend the session if it is an interactive event.\n const { windowId, sessionId } = this.sessionManager.checkAndGetSessionAndWindowId(\n !isUserInteraction,\n event.timestamp\n )\n\n const sessionIdChanged = this.sessionId !== sessionId\n const windowIdChanged = this.windowId !== windowId\n this.windowId = windowId\n this.sessionId = sessionId\n\n if (\n [FULL_SNAPSHOT_EVENT_TYPE, META_EVENT_TYPE].indexOf(event.type) === -1 &&\n (windowIdChanged || sessionIdChanged)\n ) {\n this._tryTakeFullSnapshot()\n }\n }\n\n private _tryTakeFullSnapshot(): boolean {\n // TODO this should ignore based on emit?\n if (!this._captureStarted) {\n return false\n }\n try {\n this.rrwebRecord?.takeFullSnapshot()\n return true\n } catch (e) {\n // Sometimes a race can occur where the recorder is not fully started yet, so we can't take a full snapshot.\n logger.error('Error taking full snapshot.', e)\n return false\n }\n }\n\n private _onScriptLoaded() {\n // rrweb config info: https://github.com/rrweb-io/rrweb/blob/7d5d0033258d6c29599fb08412202d9a2c7b9413/src/record/index.ts#L28\n const sessionRecordingOptions: recordOptions<eventWithTime> = {\n // select set of rrweb config options we expose to our users\n // see https://github.com/rrweb-io/rrweb/blob/master/guide.md\n blockClass: 'ph-no-capture',\n blockSelector: undefined,\n ignoreClass: 'ph-ignore-input',\n maskTextClass: 'ph-mask',\n maskTextSelector: undefined,\n maskTextFn: undefined,\n maskAllInputs: true,\n maskInputOptions: {},\n maskInputFn: undefined,\n slimDOMOptions: {},\n collectFonts: false,\n inlineStylesheet: true,\n recordCrossOriginIframes: false,\n }\n // We switched from loading all of rrweb to just the record part, but\n // keep backwards compatibility if someone hasn't upgraded PostHog\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.rrwebRecord = window.rrweb ? window.rrweb.record : window.rrwebRecord\n\n // only allows user to set our allow-listed options\n const userSessionRecordingOptions = this.instance.config.session_recording\n for (const [key, value] of Object.entries(userSessionRecordingOptions || {})) {\n if (key in sessionRecordingOptions) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n sessionRecordingOptions[key] = value\n }\n }\n\n if (!this.rrwebRecord) {\n logger.error(\n 'onScriptLoaded was called but rrwebRecord is not available. This indicates something has gone wrong.'\n )\n return\n }\n\n this.mutationRateLimiter =\n this.mutationRateLimiter ??\n new MutationRateLimiter(this.rrwebRecord, {\n onBlockedNode: (id, node) => {\n const message = `Too many mutations on node '${id}'. Rate limiting. This could be due to SVG animations or something similar`\n logger.info(message, {\n node: node,\n })\n\n this.log('[PostHog Recorder] ' + message, 'warn')\n },\n })\n\n this.stopRrweb = this.rrwebRecord({\n emit: (event) => {\n this.onRRwebEmit(event)\n },\n plugins:\n (window as any).rrwebConsoleRecord && this.isConsoleLogCaptureEnabled\n ? [(window as any).rrwebConsoleRecord.getRecordConsolePlugin()]\n : [],\n ...sessionRecordingOptions,\n })\n\n // :TRICKY: rrweb does not capture navigation within SPA-s, so hook into our $pageview events to get access to all events.\n // Dropping the initial event is fine (it's always captured by rrweb).\n this.instance._addCaptureHook((eventName) => {\n // If anything could go wrong here it has the potential to block the main loop,\n // so we catch all errors.\n try {\n if (eventName === '$pageview') {\n const href = this._maskUrl(window.location.href)\n if (!href) {\n return\n }\n this.rrwebRecord?.addCustomEvent('$pageview', { href })\n }\n } catch (e) {\n logger.error('Could not add $pageview to rrweb session', e)\n }\n })\n\n // We reset the last activity timestamp, resetting the idle timer\n this._lastActivityTimestamp = Date.now()\n this.isIdle = false\n }\n\n onRRwebEmit(rawEvent: eventWithTime) {\n if (!rawEvent || !_isObject(rawEvent)) {\n return\n }\n\n if (rawEvent.type === EventType.Meta) {\n const href = this._maskUrl(rawEvent.data.href)\n if (!href) {\n return\n }\n rawEvent.data.href = href\n }\n\n const throttledEvent = this.mutationRateLimiter\n ? this.mutationRateLimiter.throttleMutations(rawEvent)\n : rawEvent\n\n if (!throttledEvent) {\n return\n }\n\n // TODO: Re-add ensureMaxMessageSize once we are confident in it\n const event = truncateLargeConsoleLogs(throttledEvent)\n const size = JSON.stringify(event).length\n\n const properties = {\n $snapshot_bytes: size,\n $snapshot_data: event,\n $session_id: this.sessionId,\n $window_id: this.windowId,\n }\n\n this._updateWindowAndSessionIds(event)\n\n if (this.isIdle) {\n // When in an idle state we keep recording, but don't capture the events\n return\n }\n\n if (this.status !== 'disabled') {\n this._captureSnapshotBuffered(properties)\n } else {\n this.clearBuffer()\n }\n }\n\n private _maskUrl(url: string): string | undefined {\n const userSessionRecordingOptions = this.instance.config.session_recording\n\n if (userSessionRecordingOptions.maskNetworkRequestFn) {\n let networkRequest: NetworkRequest | null | undefined = {\n url,\n }\n\n networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest)\n\n return networkRequest?.url\n }\n\n return url\n }\n\n private clearBuffer(): SnapshotBuffer {\n this.buffer = undefined\n\n return {\n size: 0,\n data: [],\n sessionId: this.sessionId,\n windowId: this.windowId,\n }\n }\n\n // the intention is a buffer that (currently) is used only after a decide response enables session recording\n // it is called ever X seconds using the flushBufferTimer so that we don't have to wait for the buffer to fill up\n // when it is called on a timer it assumes that it can definitely flush\n // it is flushed when the session id changes or the size of the buffered data gets too great (1mb by default)\n // first change: if the recording is in buffering mode,\n // flush buffer simply resets the timer and returns the existing flush buffer\n private _flushBuffer() {\n if (this.flushBufferTimer) {\n clearTimeout(this.flushBufferTimer)\n this.flushBufferTimer = undefined\n }\n\n const minimumDuration = this._minimumDuration\n const sessionDuration = this.sessionDuration\n const isBelowMinimumDuration =\n _isNumber(minimumDuration) && _isNumber(sessionDuration) && sessionDuration < minimumDuration\n\n if (this.status === 'buffering' || isBelowMinimumDuration) {\n this.flushBufferTimer = setTimeout(() => {\n this._flushBuffer()\n }, RECORDING_BUFFER_TIMEOUT)\n return this.buffer || this.clearBuffer()\n }\n\n if (this.buffer && this.buffer.data.length !== 0) {\n this._captureSnapshot({\n $snapshot_bytes: this.buffer.size,\n $snapshot_data: this.buffer.data,\n $session_id: this.buffer.sessionId,\n $window_id: this.buffer.windowId,\n })\n\n return this.clearBuffer()\n } else {\n return this.buffer || this.clearBuffer()\n }\n }\n\n private _captureSnapshotBuffered(properties: Properties) {\n const additionalBytes = 2 + (this.buffer?.data.length || 0) // 2 bytes for the array brackets and 1 byte for each comma\n if (\n !this.buffer ||\n this.buffer.size + properties.$snapshot_bytes + additionalBytes > RECORDING_MAX_EVENT_SIZE ||\n this.buffer.sessionId !== this.sessionId\n ) {\n this.buffer = this._flushBuffer()\n }\n\n this.buffer.size += properties.$snapshot_bytes\n this.buffer.data.push(properties.$snapshot_data)\n\n if (!this.flushBufferTimer) {\n this.flushBufferTimer = setTimeout(() => {\n this._flushBuffer()\n }, RECORDING_BUFFER_TIMEOUT)\n }\n }\n\n private _captureSnapshot(properties: Properties) {\n // :TRICKY: Make sure we batch these requests, use a custom endpoint and don't truncate the strings.\n this.instance.capture('$snapshot', properties, {\n transport: 'XHR',\n method: 'POST',\n endpoint: this._endpoint,\n _noTruncate: true,\n _batchKey: SESSION_RECORDING_BATCH_KEY,\n _metrics: {\n rrweb_full_snapshot: properties.$snapshot_data.type === FULL_SNAPSHOT_EVENT_TYPE,\n },\n })\n }\n}\n"]}
1
+ {"version":3,"file":"sessionrecording.js","sourceRoot":"","sources":["../../../../src/extensions/replay/sessionrecording.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE,\n SESSION_RECORDING_ENABLED_SERVER_SIDE,\n SESSION_RECORDING_IS_SAMPLED,\n SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE,\n} from '../../constants'\nimport {\n FULL_SNAPSHOT_EVENT_TYPE,\n INCREMENTAL_SNAPSHOT_EVENT_TYPE,\n META_EVENT_TYPE,\n MutationRateLimiter,\n recordOptions,\n rrwebRecord,\n truncateLargeConsoleLogs,\n} from './sessionrecording-utils'\nimport { PostHog } from '../../posthog-core'\nimport { DecideResponse, NetworkRequest, Properties } from '../../types'\nimport { EventType, type eventWithTime, type listenerHandler } from '@rrweb/types'\nimport Config from '../../config'\nimport { _timestamp, loadScript } from '../../utils'\n\nimport { _isBoolean, _isNull, _isNumber, _isObject, _isString, _isUndefined } from '../../utils/type-utils'\nimport { logger } from '../../utils/logger'\n\nconst BASE_ENDPOINT = '/s/'\n\nexport const RECORDING_IDLE_ACTIVITY_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes\nexport const RECORDING_MAX_EVENT_SIZE = 1024 * 1024 * 0.9 // ~1mb (with some wiggle room)\nexport const RECORDING_BUFFER_TIMEOUT = 2000 // 2 seconds\nexport const SESSION_RECORDING_BATCH_KEY = 'recordings'\n\n// NOTE: Importing this type is problematic as we can't safely bundle it to a TS definition so, instead we redefine.\n// import type { record } from 'rrweb2/typings'\n// import type { recordOptions } from 'rrweb/typings/types'\n\n// Copied from rrweb typings to avoid import\nenum IncrementalSource {\n Mutation = 0,\n MouseMove = 1,\n MouseInteraction = 2,\n Scroll = 3,\n ViewportResize = 4,\n Input = 5,\n TouchMove = 6,\n MediaInteraction = 7,\n StyleSheetRule = 8,\n CanvasMutation = 9,\n Font = 10,\n Log = 11,\n Drag = 12,\n StyleDeclaration = 13,\n Selection = 14,\n AdoptedStyleSheet = 15,\n}\n\nconst ACTIVE_SOURCES = [\n IncrementalSource.MouseMove,\n IncrementalSource.MouseInteraction,\n IncrementalSource.Scroll,\n IncrementalSource.ViewportResize,\n IncrementalSource.Input,\n IncrementalSource.TouchMove,\n IncrementalSource.MediaInteraction,\n IncrementalSource.Drag,\n]\n\n/**\n * Session recording starts in buffering mode while waiting for decide response\n * Once the response is received it might be disabled, active or sampled\n * When sampled that means a sample rate is set and the last time the session id was rotated\n * the sample rate determined this session should be sent to the server.\n */\ntype SessionRecordingStatus = 'disabled' | 'sampled' | 'active' | 'buffering'\n\ninterface SnapshotBuffer {\n size: number\n data: any[]\n sessionId: string | null\n windowId: string | null\n}\n\nexport class SessionRecording {\n private _linkedFlagSeen: boolean = false\n private instance: PostHog\n private _endpoint: string\n private windowId: string | null\n private sessionId: string | null\n private _lastActivityTimestamp: number = Date.now()\n private flushBufferTimer?: any\n private buffer?: SnapshotBuffer\n private mutationRateLimiter?: MutationRateLimiter\n private _captureStarted: boolean\n private stopRrweb: listenerHandler | undefined\n private receivedDecide: boolean\n private rrwebRecord: rrwebRecord | undefined\n private isIdle = false\n private _linkedFlag: string | null = null\n private _sampleRate: number | null = null\n private _minimumDuration: number | null = null\n\n public get started(): boolean {\n // TODO could we use status instead of _captureStarted?\n return this._captureStarted\n }\n\n private get sessionManager() {\n if (!this.instance.sessionManager) {\n logger.error('Session recording started without valid sessionManager')\n throw new Error('Session recording started without valid sessionManager. This is a bug.')\n }\n\n return this.instance.sessionManager\n }\n\n private get isSampled(): boolean | null {\n if (_isNumber(this._sampleRate)) {\n return this.instance.get_property(SESSION_RECORDING_IS_SAMPLED)\n } else {\n return null\n }\n }\n\n private get sessionDuration(): number | null {\n const mostRecentSnapshot = this.buffer?.data[this.buffer?.data.length - 1]\n const { sessionStartTimestamp } = this.sessionManager.checkAndGetSessionAndWindowId(true)\n return mostRecentSnapshot ? mostRecentSnapshot.timestamp - sessionStartTimestamp : null\n }\n\n private get isRecordingEnabled() {\n const enabled_server_side = !!this.instance.get_property(SESSION_RECORDING_ENABLED_SERVER_SIDE)\n const enabled_client_side = !this.instance.config.disable_session_recording\n return enabled_server_side && enabled_client_side\n }\n\n private get isConsoleLogCaptureEnabled() {\n const enabled_server_side = !!this.instance.get_property(CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE)\n const enabled_client_side = this.instance.config.enable_recording_console_log\n return enabled_client_side ?? enabled_server_side\n }\n\n private get recordingVersion() {\n const recordingVersion_server_side = this.instance.get_property(SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE)\n const recordingVersion_client_side = this.instance.config.session_recording?.recorderVersion\n return recordingVersion_client_side || recordingVersion_server_side || 'v1'\n }\n\n /**\n * defaults to buffering mode until a decide response is received\n * once a decide response is received status can be disabled, active or sampled\n */\n private get status(): SessionRecordingStatus {\n if (!this.receivedDecide) {\n return 'buffering'\n }\n\n if (!this.isRecordingEnabled) {\n return 'disabled'\n }\n\n if (_isString(this._linkedFlag) && !this._linkedFlagSeen) {\n return 'buffering'\n }\n\n if (_isBoolean(this.isSampled)) {\n return this.isSampled ? 'sampled' : 'disabled'\n } else {\n return 'active'\n }\n }\n\n constructor(instance: PostHog) {\n this.instance = instance\n this._captureStarted = false\n this._endpoint = BASE_ENDPOINT\n this.stopRrweb = undefined\n this.receivedDecide = false\n\n window.addEventListener('beforeunload', () => {\n this._flushBuffer()\n })\n\n if (!this.instance.sessionManager) {\n logger.error('Session recording started without valid sessionManager')\n throw new Error('Session recording started without valid sessionManager. This is a bug.')\n }\n\n const { sessionId, windowId } = this.sessionManager.checkAndGetSessionAndWindowId(true)\n this.windowId = windowId\n this.sessionId = sessionId\n\n this.buffer = this.clearBuffer()\n }\n\n startRecordingIfEnabled() {\n if (this.isRecordingEnabled) {\n this.startCaptureAndTrySendingQueuedSnapshots()\n } else {\n this.stopRecording()\n this.clearBuffer()\n }\n }\n\n stopRecording() {\n if (this._captureStarted && this.stopRrweb) {\n this.stopRrweb()\n this.stopRrweb = undefined\n this._captureStarted = false\n }\n }\n\n private makeSamplingDecision(sessionId: string): void {\n const sessionIdChanged = this.sessionId !== sessionId\n\n if (!_isNumber(this._sampleRate)) {\n this.instance.persistence?.register({\n [SESSION_RECORDING_IS_SAMPLED]: null,\n })\n return\n }\n\n const storedIsSampled = this.isSampled\n\n /**\n * if we get this far then we should make a sampling decision.\n * When the session id changes or there is no stored sampling decision for this session id\n * then we should make a new decision.\n *\n * Otherwise, we should use the stored decision.\n */\n let shouldSample: boolean\n if (sessionIdChanged || !_isBoolean(storedIsSampled)) {\n const randomNumber = Math.random()\n shouldSample = randomNumber < this._sampleRate\n } else {\n shouldSample = storedIsSampled\n }\n\n if (!shouldSample) {\n logger.warn(\n `[SessionSampling] Sample rate (${this._sampleRate}) has determined that this sessionId (${sessionId}) will not be sent to the server.`\n )\n }\n\n this.instance.persistence?.register({\n [SESSION_RECORDING_IS_SAMPLED]: shouldSample,\n })\n }\n\n afterDecideResponse(response: DecideResponse) {\n if (this.instance.persistence) {\n this.instance.persistence.register({\n [SESSION_RECORDING_ENABLED_SERVER_SIDE]: !!response['sessionRecording'],\n [CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE]: response.sessionRecording?.consoleLogRecordingEnabled,\n [SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE]: response.sessionRecording?.recorderVersion,\n })\n }\n\n const receivedSampleRate = response.sessionRecording?.sampleRate\n this._sampleRate =\n _isUndefined(receivedSampleRate) || _isNull(receivedSampleRate) ? null : parseFloat(receivedSampleRate)\n\n const receivedMinimumDuration = response.sessionRecording?.minimumDurationMilliseconds\n this._minimumDuration = _isUndefined(receivedMinimumDuration) ? null : receivedMinimumDuration\n\n this._linkedFlag = response.sessionRecording?.linkedFlag || null\n\n if (response.sessionRecording?.endpoint) {\n this._endpoint = response.sessionRecording?.endpoint\n }\n\n if (_isNumber(this._sampleRate)) {\n this.sessionManager.onSessionId((sessionId) => {\n this.makeSamplingDecision(sessionId)\n })\n }\n\n if (_isString(this._linkedFlag)) {\n const linkedFlag = this._linkedFlag\n this.instance.onFeatureFlags((flags) => {\n this._linkedFlagSeen = flags.includes(linkedFlag)\n })\n }\n\n this.receivedDecide = true\n this.startRecordingIfEnabled()\n }\n\n log(message: string, level: 'log' | 'warn' | 'error' = 'log') {\n this.instance.sessionRecording?.onRRwebEmit({\n type: 6,\n data: {\n plugin: 'rrweb/console@1',\n payload: {\n level,\n trace: [],\n // Even though it is a string we stringify it as that's what rrweb expects\n payload: [JSON.stringify(message)],\n },\n },\n timestamp: _timestamp(),\n })\n }\n\n private startCaptureAndTrySendingQueuedSnapshots() {\n this._startCapture()\n }\n\n private _startCapture() {\n if (_isUndefined(Object.assign)) {\n // According to the rrweb docs, rrweb is not supported on IE11 and below:\n // \"rrweb does not support IE11 and below because it uses the MutationObserver API which was supported by these browsers.\"\n // https://github.com/rrweb-io/rrweb/blob/master/guide.md#compatibility-note\n //\n // However, MutationObserver does exist on IE11, it just doesn't work well and does not detect all changes.\n // Instead, when we load \"recorder.js\", the first JS error is about \"Object.assign\" being undefined.\n // Thus instead of MutationObserver, we look for this function and block recording if it's undefined.\n return\n }\n\n // We do not switch recorder versions midway through a recording.\n if (this._captureStarted || this.instance.config.disable_session_recording) {\n return\n }\n\n this._captureStarted = true\n // We want to ensure the sessionManager is reset if necessary on load of the recorder\n this.sessionManager.checkAndGetSessionAndWindowId()\n\n const recorderJS = this.recordingVersion === 'v2' ? 'recorder-v2.js' : 'recorder.js'\n\n // If recorder.js is already loaded (if array.full.js snippet is used or posthog-js/dist/recorder is\n // imported) or matches the requested recorder version, don't load script. Otherwise, remotely import\n // recorder.js from cdn since it hasn't been loaded.\n if (this.instance.__loaded_recorder_version !== this.recordingVersion) {\n loadScript(this.instance.config.api_host + `/static/${recorderJS}?v=${Config.LIB_VERSION}`, (err) => {\n if (err) {\n return logger.error(`Could not load ${recorderJS}`, err)\n }\n\n this._onScriptLoaded()\n })\n } else {\n this._onScriptLoaded()\n }\n }\n\n private _isInteractiveEvent(event: eventWithTime) {\n return event.type === INCREMENTAL_SNAPSHOT_EVENT_TYPE && ACTIVE_SOURCES.indexOf(event.data?.source) !== -1\n }\n\n private _updateWindowAndSessionIds(event: eventWithTime) {\n // Some recording events are triggered by non-user events (e.g. \"X minutes ago\" text updating on the screen).\n // We don't want to extend the session or trigger a new session in these cases. These events are designated by event\n // type -> incremental update, and source -> mutation.\n\n const isUserInteraction = this._isInteractiveEvent(event)\n\n if (!isUserInteraction && !this.isIdle) {\n // We check if the lastActivityTimestamp is old enough to go idle\n if (event.timestamp - this._lastActivityTimestamp > RECORDING_IDLE_ACTIVITY_TIMEOUT_MS) {\n this.isIdle = true\n }\n }\n\n if (isUserInteraction) {\n this._lastActivityTimestamp = event.timestamp\n if (this.isIdle) {\n // Remove the idle state if set and trigger a full snapshot as we will have ignored previous mutations\n this.isIdle = false\n this._tryTakeFullSnapshot()\n }\n }\n\n if (this.isIdle) {\n return\n }\n\n // We only want to extend the session if it is an interactive event.\n const { windowId, sessionId } = this.sessionManager.checkAndGetSessionAndWindowId(\n !isUserInteraction,\n event.timestamp\n )\n\n const sessionIdChanged = this.sessionId !== sessionId\n const windowIdChanged = this.windowId !== windowId\n this.windowId = windowId\n this.sessionId = sessionId\n\n if (\n [FULL_SNAPSHOT_EVENT_TYPE, META_EVENT_TYPE].indexOf(event.type) === -1 &&\n (windowIdChanged || sessionIdChanged)\n ) {\n this._tryTakeFullSnapshot()\n }\n }\n\n private _tryTakeFullSnapshot(): boolean {\n // TODO this should ignore based on emit?\n if (!this._captureStarted) {\n return false\n }\n try {\n this.rrwebRecord?.takeFullSnapshot()\n return true\n } catch (e) {\n // Sometimes a race can occur where the recorder is not fully started yet, so we can't take a full snapshot.\n logger.error('Error taking full snapshot.', e)\n return false\n }\n }\n\n private _onScriptLoaded() {\n // rrweb config info: https://github.com/rrweb-io/rrweb/blob/7d5d0033258d6c29599fb08412202d9a2c7b9413/src/record/index.ts#L28\n const sessionRecordingOptions: recordOptions<eventWithTime> = {\n // select set of rrweb config options we expose to our users\n // see https://github.com/rrweb-io/rrweb/blob/master/guide.md\n blockClass: 'ph-no-capture',\n blockSelector: undefined,\n ignoreClass: 'ph-ignore-input',\n maskTextClass: 'ph-mask',\n maskTextSelector: undefined,\n maskTextFn: undefined,\n maskAllInputs: true,\n maskInputOptions: {},\n maskInputFn: undefined,\n slimDOMOptions: {},\n collectFonts: false,\n inlineStylesheet: true,\n recordCrossOriginIframes: false,\n }\n // We switched from loading all of rrweb to just the record part, but\n // keep backwards compatibility if someone hasn't upgraded PostHog\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.rrwebRecord = window.rrweb ? window.rrweb.record : window.rrwebRecord\n\n // only allows user to set our allow-listed options\n const userSessionRecordingOptions = this.instance.config.session_recording\n for (const [key, value] of Object.entries(userSessionRecordingOptions || {})) {\n if (key in sessionRecordingOptions) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n sessionRecordingOptions[key] = value\n }\n }\n\n if (!this.rrwebRecord) {\n logger.error(\n 'onScriptLoaded was called but rrwebRecord is not available. This indicates something has gone wrong.'\n )\n return\n }\n\n this.mutationRateLimiter =\n this.mutationRateLimiter ??\n new MutationRateLimiter(this.rrwebRecord, {\n onBlockedNode: (id, node) => {\n const message = `Too many mutations on node '${id}'. Rate limiting. This could be due to SVG animations or something similar`\n logger.info(message, {\n node: node,\n })\n\n this.log('[PostHog Recorder] ' + message, 'warn')\n },\n })\n\n this.stopRrweb = this.rrwebRecord({\n emit: (event) => {\n this.onRRwebEmit(event)\n },\n plugins:\n (window as any).rrwebConsoleRecord && this.isConsoleLogCaptureEnabled\n ? [(window as any).rrwebConsoleRecord.getRecordConsolePlugin()]\n : [],\n ...sessionRecordingOptions,\n })\n\n // :TRICKY: rrweb does not capture navigation within SPA-s, so hook into our $pageview events to get access to all events.\n // Dropping the initial event is fine (it's always captured by rrweb).\n this.instance._addCaptureHook((eventName) => {\n // If anything could go wrong here it has the potential to block the main loop,\n // so we catch all errors.\n try {\n if (eventName === '$pageview') {\n const href = this._maskUrl(window.location.href)\n if (!href) {\n return\n }\n this.rrwebRecord?.addCustomEvent('$pageview', { href })\n }\n } catch (e) {\n logger.error('Could not add $pageview to rrweb session', e)\n }\n })\n\n // We reset the last activity timestamp, resetting the idle timer\n this._lastActivityTimestamp = Date.now()\n this.isIdle = false\n }\n\n onRRwebEmit(rawEvent: eventWithTime) {\n if (!rawEvent || !_isObject(rawEvent)) {\n return\n }\n\n if (rawEvent.type === EventType.Meta) {\n const href = this._maskUrl(rawEvent.data.href)\n if (!href) {\n return\n }\n rawEvent.data.href = href\n }\n\n const throttledEvent = this.mutationRateLimiter\n ? this.mutationRateLimiter.throttleMutations(rawEvent)\n : rawEvent\n\n if (!throttledEvent) {\n return\n }\n\n // TODO: Re-add ensureMaxMessageSize once we are confident in it\n const event = truncateLargeConsoleLogs(throttledEvent)\n const size = JSON.stringify(event).length\n\n const properties = {\n $snapshot_bytes: size,\n $snapshot_data: event,\n $session_id: this.sessionId,\n $window_id: this.windowId,\n }\n\n this._updateWindowAndSessionIds(event)\n\n if (this.isIdle) {\n // When in an idle state we keep recording, but don't capture the events\n return\n }\n\n if (this.status !== 'disabled') {\n this._captureSnapshotBuffered(properties)\n } else {\n this.clearBuffer()\n }\n }\n\n private _maskUrl(url: string): string | undefined {\n const userSessionRecordingOptions = this.instance.config.session_recording\n\n if (userSessionRecordingOptions.maskNetworkRequestFn) {\n let networkRequest: NetworkRequest | null | undefined = {\n url,\n }\n\n networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest)\n\n return networkRequest?.url\n }\n\n return url\n }\n\n private clearBuffer(): SnapshotBuffer {\n this.buffer = undefined\n\n return {\n size: 0,\n data: [],\n sessionId: this.sessionId,\n windowId: this.windowId,\n }\n }\n\n // the intention is a buffer that (currently) is used only after a decide response enables session recording\n // it is called ever X seconds using the flushBufferTimer so that we don't have to wait for the buffer to fill up\n // when it is called on a timer it assumes that it can definitely flush\n // it is flushed when the session id changes or the size of the buffered data gets too great (1mb by default)\n // first change: if the recording is in buffering mode,\n // flush buffer simply resets the timer and returns the existing flush buffer\n private _flushBuffer() {\n if (this.flushBufferTimer) {\n clearTimeout(this.flushBufferTimer)\n this.flushBufferTimer = undefined\n }\n\n const minimumDuration = this._minimumDuration\n const sessionDuration = this.sessionDuration\n const isBelowMinimumDuration =\n _isNumber(minimumDuration) && _isNumber(sessionDuration) && sessionDuration < minimumDuration\n\n if (this.status === 'buffering' || isBelowMinimumDuration) {\n this.flushBufferTimer = setTimeout(() => {\n this._flushBuffer()\n }, RECORDING_BUFFER_TIMEOUT)\n return this.buffer || this.clearBuffer()\n }\n\n if (this.buffer && this.buffer.data.length !== 0) {\n this._captureSnapshot({\n $snapshot_bytes: this.buffer.size,\n $snapshot_data: this.buffer.data,\n $session_id: this.buffer.sessionId,\n $window_id: this.buffer.windowId,\n })\n\n return this.clearBuffer()\n } else {\n return this.buffer || this.clearBuffer()\n }\n }\n\n private _captureSnapshotBuffered(properties: Properties) {\n const additionalBytes = 2 + (this.buffer?.data.length || 0) // 2 bytes for the array brackets and 1 byte for each comma\n if (\n !this.buffer ||\n this.buffer.size + properties.$snapshot_bytes + additionalBytes > RECORDING_MAX_EVENT_SIZE ||\n this.buffer.sessionId !== this.sessionId\n ) {\n this.buffer = this._flushBuffer()\n }\n\n this.buffer.size += properties.$snapshot_bytes\n this.buffer.data.push(properties.$snapshot_data)\n\n if (!this.flushBufferTimer) {\n this.flushBufferTimer = setTimeout(() => {\n this._flushBuffer()\n }, RECORDING_BUFFER_TIMEOUT)\n }\n }\n\n private _captureSnapshot(properties: Properties) {\n // :TRICKY: Make sure we batch these requests, use a custom endpoint and don't truncate the strings.\n this.instance.capture('$snapshot', properties, {\n transport: 'XHR',\n method: 'POST',\n endpoint: this._endpoint,\n _noTruncate: true,\n _batchKey: SESSION_RECORDING_BATCH_KEY,\n _metrics: {\n rrweb_full_snapshot: properties.$snapshot_data.type === FULL_SNAPSHOT_EVENT_TYPE,\n },\n })\n }\n}\n"]}
@@ -9,9 +9,9 @@ var __values = (this && this.__values) || function(o) {
9
9
  };
10
10
  throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
11
11
  };
12
- import { logger } from '../../utils';
13
12
  import { isLocalhost } from '../../utils/request-utils';
14
13
  import { _isUndefined } from '../../utils/type-utils';
14
+ import { logger } from '../../utils/logger';
15
15
  var PERFORMANCE_EVENTS_MAPPING = {
16
16
  // BASE_PERFORMANCE_EVENT_COLUMNS
17
17
  entryType: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"web-performance.js","sourceRoot":"","sources":["../../../../src/extensions/replay/web-performance.ts"],"names":[],"mappings":"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","sourcesContent":["import { logger } from '../../utils'\nimport { PostHog } from '../../posthog-core'\nimport { DecideResponse, NetworkRequest } from '../../types'\nimport { isLocalhost } from '../../utils/request-utils'\n\nimport { _isUndefined } from '../../utils/type-utils'\n\nconst PERFORMANCE_EVENTS_MAPPING: { [key: string]: number } = {\n // BASE_PERFORMANCE_EVENT_COLUMNS\n entryType: 0,\n timeOrigin: 1,\n name: 2,\n\n // RESOURCE_EVENT_COLUMNS\n startTime: 3,\n redirectStart: 4,\n redirectEnd: 5,\n workerStart: 6,\n fetchStart: 7,\n domainLookupStart: 8,\n domainLookupEnd: 9,\n connectStart: 10,\n secureConnectionStart: 11,\n connectEnd: 12,\n requestStart: 13,\n responseStart: 14,\n responseEnd: 15,\n decodedBodySize: 16,\n encodedBodySize: 17,\n initiatorType: 18,\n nextHopProtocol: 19,\n renderBlockingStatus: 20,\n responseStatus: 21,\n transferSize: 22,\n\n // LARGEST_CONTENTFUL_PAINT_EVENT_COLUMNS\n element: 23,\n renderTime: 24,\n loadTime: 25,\n size: 26,\n id: 27,\n url: 28,\n\n // NAVIGATION_EVENT_COLUMNS\n domComplete: 29,\n domContentLoadedEvent: 30,\n domInteractive: 31,\n loadEventEnd: 32,\n loadEventStart: 33,\n redirectCount: 34,\n navigationType: 35,\n unloadEventEnd: 36,\n unloadEventStart: 37,\n\n // Added after v1\n duration: 39,\n timestamp: 40,\n\n // NOTE: CURRENTLY UNSUPPORTED\n // EVENT_TIMING_EVENT_COLUMNS\n // processingStart: null,\n // processingEnd: null,\n\n // MARK_AND_MEASURE_EVENT_COLUMNS\n // detail: null,\n}\n\nconst ENTRY_TYPES_TO_OBSERVE = [\n // 'event', // This is too noisy as it covers all browser events\n 'first-input',\n // 'mark', // Mark is used too liberally. We would need to filter for specific marks\n // 'measure', // Measure is used too liberally. We would need to filter for specific measures\n 'navigation',\n 'paint',\n 'resource',\n]\n\nconst PERFORMANCE_INGESTION_ENDPOINT = '/e/'\n// Don't monitor posthog paths because then events cause performance events which are events and the snake eats its tail 😱\nconst POSTHOG_PATHS_TO_IGNORE = ['/s/', PERFORMANCE_INGESTION_ENDPOINT]\n\nexport class WebPerformanceObserver {\n instance: PostHog\n remoteEnabled: boolean | undefined\n observer: PerformanceObserver | undefined\n\n // Util to help developers working on this feature manually override\n _forceAllowLocalhost = false\n\n constructor(instance: PostHog) {\n this.instance = instance\n }\n\n startObservingIfEnabled() {\n if (this.isEnabled()) {\n this.startObserving()\n } else {\n this.stopObserving()\n }\n }\n\n startObserving() {\n if (this.observer) {\n return\n }\n\n if (_isUndefined(window?.PerformanceObserver?.supportedEntryTypes)) {\n logger.info(\n '[PerformanceObserver] not started because PerformanceObserver is not supported by this browser.'\n )\n return\n }\n\n if (isLocalhost() && !this._forceAllowLocalhost) {\n logger.info('[PerformanceObserver] not started because we are on localhost.')\n return\n }\n\n try {\n // compat checked above with early return\n // eslint-disable-next-line compat/compat\n this.observer = new PerformanceObserver((list) => {\n list.getEntries().forEach((entry) => {\n this._capturePerformanceEvent(entry)\n })\n })\n\n // compat checked above with early return\n // eslint-disable-next-line compat/compat\n const entryTypes = PerformanceObserver.supportedEntryTypes.filter((x) => ENTRY_TYPES_TO_OBSERVE.includes(x))\n\n entryTypes.forEach((entryType) => {\n this.observer?.observe({ type: entryType, buffered: true })\n })\n } catch (e) {\n logger.error('PostHog failed to start performance observer', e)\n this.stopObserving()\n }\n }\n\n stopObserving() {\n if (this.observer) {\n this.observer.disconnect()\n this.observer = undefined\n }\n }\n\n isObserving() {\n return !!this.observer\n }\n\n isEnabled() {\n return this.instance.config.capture_performance ?? this.remoteEnabled ?? false\n }\n\n afterDecideResponse(response: DecideResponse) {\n this.remoteEnabled = response.capturePerformance || false\n if (this.isEnabled()) {\n this.startObserving()\n }\n }\n\n _capturePerformanceEvent(event: PerformanceEntry) {\n // NOTE: We don't want to capture our own request events.\n\n if (event.name.indexOf(this.instance.config.api_host) === 0) {\n const path = event.name.replace(this.instance.config.api_host, '')\n\n if (POSTHOG_PATHS_TO_IGNORE.find((x) => path.indexOf(x) === 0)) {\n return\n }\n }\n\n // NOTE: This is minimal atm but will include more options when we move to the\n // built-in rrweb network recorder\n let networkRequest: NetworkRequest | null | undefined = {\n url: event.name,\n }\n\n const userSessionRecordingOptions = this.instance.config.session_recording\n\n if (userSessionRecordingOptions.maskNetworkRequestFn) {\n networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest)\n }\n\n if (!networkRequest) {\n return\n }\n\n const eventJson = event.toJSON()\n eventJson.name = networkRequest.url\n const properties: { [key: number]: any } = {}\n // kudos to sentry javascript sdk for excellent background on why to use Date.now() here\n // https://github.com/getsentry/sentry-javascript/blob/e856e40b6e71a73252e788cd42b5260f81c9c88e/packages/utils/src/time.ts#L70\n // can't start observer if performance.now() is not available\n // eslint-disable-next-line compat/compat\n const timeOrigin = Math.floor(Date.now() - performance.now())\n properties[PERFORMANCE_EVENTS_MAPPING['timeOrigin']] = timeOrigin\n // clickhouse can't ingest timestamps that are floats\n // (in this case representing fractions of a millisecond we don't care about anyway)\n properties[PERFORMANCE_EVENTS_MAPPING['timestamp']] = Math.floor(timeOrigin + event.startTime)\n for (const key in PERFORMANCE_EVENTS_MAPPING) {\n if (!_isUndefined(eventJson[key])) {\n properties[PERFORMANCE_EVENTS_MAPPING[key]] = eventJson[key]\n }\n }\n\n this.capturePerformanceEvent(properties)\n\n if (exposesServerTiming(event)) {\n for (const timing of event.serverTiming || []) {\n this.capturePerformanceEvent({\n [PERFORMANCE_EVENTS_MAPPING['timeOrigin']]: timeOrigin,\n [PERFORMANCE_EVENTS_MAPPING['timestamp']]: Math.floor(timeOrigin + event.startTime),\n [PERFORMANCE_EVENTS_MAPPING['name']]: timing.name,\n [PERFORMANCE_EVENTS_MAPPING['duration']]: timing.duration,\n // the spec has a closed list of possible types\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/entryType\n // but, we need to know this was a server timing so that we know to\n // match it to the appropriate navigation or resource timing\n // that matching will have to be on timestamp and $current_url\n [PERFORMANCE_EVENTS_MAPPING['entryType']]: 'serverTiming',\n })\n }\n }\n }\n\n /**\n * :TRICKY: Make sure we batch these requests, and don't truncate the strings.\n */\n private capturePerformanceEvent(properties: { [key: number]: any }) {\n const timestamp = properties[PERFORMANCE_EVENTS_MAPPING['timestamp']]\n\n this.instance.sessionRecording?.onRRwebEmit({\n type: 6, // EventType.Plugin,\n data: {\n plugin: 'posthog/network@1',\n payload: properties,\n },\n timestamp,\n })\n\n // this.instance.capture('$performance_event', properties, {\n // transport: 'XHR',\n // method: 'POST',\n // endpoint: PERFORMANCE_INGESTION_ENDPOINT,\n // _noTruncate: true,\n // _batchKey: 'performanceEvent',\n // })\n }\n}\n\n/**\n * Check if this PerformanceEntry is either a PerformanceResourceTiming or a PerformanceNavigationTiming\n * NB PerformanceNavigationTiming extends PerformanceResourceTiming\n * Here we don't care which interface it implements as both expose `serverTimings`\n */\nconst exposesServerTiming = (event: PerformanceEntry): event is PerformanceResourceTiming =>\n event.entryType === 'navigation' || event.entryType === 'resource'\n"]}
1
+ {"version":3,"file":"web-performance.js","sourceRoot":"","sources":["../../../../src/extensions/replay/web-performance.ts"],"names":[],"mappings":"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","sourcesContent":["import { PostHog } from '../../posthog-core'\nimport { DecideResponse, NetworkRequest } from '../../types'\nimport { isLocalhost } from '../../utils/request-utils'\n\nimport { _isUndefined } from '../../utils/type-utils'\nimport { logger } from '../../utils/logger'\n\nconst PERFORMANCE_EVENTS_MAPPING: { [key: string]: number } = {\n // BASE_PERFORMANCE_EVENT_COLUMNS\n entryType: 0,\n timeOrigin: 1,\n name: 2,\n\n // RESOURCE_EVENT_COLUMNS\n startTime: 3,\n redirectStart: 4,\n redirectEnd: 5,\n workerStart: 6,\n fetchStart: 7,\n domainLookupStart: 8,\n domainLookupEnd: 9,\n connectStart: 10,\n secureConnectionStart: 11,\n connectEnd: 12,\n requestStart: 13,\n responseStart: 14,\n responseEnd: 15,\n decodedBodySize: 16,\n encodedBodySize: 17,\n initiatorType: 18,\n nextHopProtocol: 19,\n renderBlockingStatus: 20,\n responseStatus: 21,\n transferSize: 22,\n\n // LARGEST_CONTENTFUL_PAINT_EVENT_COLUMNS\n element: 23,\n renderTime: 24,\n loadTime: 25,\n size: 26,\n id: 27,\n url: 28,\n\n // NAVIGATION_EVENT_COLUMNS\n domComplete: 29,\n domContentLoadedEvent: 30,\n domInteractive: 31,\n loadEventEnd: 32,\n loadEventStart: 33,\n redirectCount: 34,\n navigationType: 35,\n unloadEventEnd: 36,\n unloadEventStart: 37,\n\n // Added after v1\n duration: 39,\n timestamp: 40,\n\n // NOTE: CURRENTLY UNSUPPORTED\n // EVENT_TIMING_EVENT_COLUMNS\n // processingStart: null,\n // processingEnd: null,\n\n // MARK_AND_MEASURE_EVENT_COLUMNS\n // detail: null,\n}\n\nconst ENTRY_TYPES_TO_OBSERVE = [\n // 'event', // This is too noisy as it covers all browser events\n 'first-input',\n // 'mark', // Mark is used too liberally. We would need to filter for specific marks\n // 'measure', // Measure is used too liberally. We would need to filter for specific measures\n 'navigation',\n 'paint',\n 'resource',\n]\n\nconst PERFORMANCE_INGESTION_ENDPOINT = '/e/'\n// Don't monitor posthog paths because then events cause performance events which are events and the snake eats its tail 😱\nconst POSTHOG_PATHS_TO_IGNORE = ['/s/', PERFORMANCE_INGESTION_ENDPOINT]\n\nexport class WebPerformanceObserver {\n instance: PostHog\n remoteEnabled: boolean | undefined\n observer: PerformanceObserver | undefined\n\n // Util to help developers working on this feature manually override\n _forceAllowLocalhost = false\n\n constructor(instance: PostHog) {\n this.instance = instance\n }\n\n startObservingIfEnabled() {\n if (this.isEnabled()) {\n this.startObserving()\n } else {\n this.stopObserving()\n }\n }\n\n startObserving() {\n if (this.observer) {\n return\n }\n\n if (_isUndefined(window?.PerformanceObserver?.supportedEntryTypes)) {\n logger.info(\n '[PerformanceObserver] not started because PerformanceObserver is not supported by this browser.'\n )\n return\n }\n\n if (isLocalhost() && !this._forceAllowLocalhost) {\n logger.info('[PerformanceObserver] not started because we are on localhost.')\n return\n }\n\n try {\n // compat checked above with early return\n // eslint-disable-next-line compat/compat\n this.observer = new PerformanceObserver((list) => {\n list.getEntries().forEach((entry) => {\n this._capturePerformanceEvent(entry)\n })\n })\n\n // compat checked above with early return\n // eslint-disable-next-line compat/compat\n const entryTypes = PerformanceObserver.supportedEntryTypes.filter((x) => ENTRY_TYPES_TO_OBSERVE.includes(x))\n\n entryTypes.forEach((entryType) => {\n this.observer?.observe({ type: entryType, buffered: true })\n })\n } catch (e) {\n logger.error('PostHog failed to start performance observer', e)\n this.stopObserving()\n }\n }\n\n stopObserving() {\n if (this.observer) {\n this.observer.disconnect()\n this.observer = undefined\n }\n }\n\n isObserving() {\n return !!this.observer\n }\n\n isEnabled() {\n return this.instance.config.capture_performance ?? this.remoteEnabled ?? false\n }\n\n afterDecideResponse(response: DecideResponse) {\n this.remoteEnabled = response.capturePerformance || false\n if (this.isEnabled()) {\n this.startObserving()\n }\n }\n\n _capturePerformanceEvent(event: PerformanceEntry) {\n // NOTE: We don't want to capture our own request events.\n\n if (event.name.indexOf(this.instance.config.api_host) === 0) {\n const path = event.name.replace(this.instance.config.api_host, '')\n\n if (POSTHOG_PATHS_TO_IGNORE.find((x) => path.indexOf(x) === 0)) {\n return\n }\n }\n\n // NOTE: This is minimal atm but will include more options when we move to the\n // built-in rrweb network recorder\n let networkRequest: NetworkRequest | null | undefined = {\n url: event.name,\n }\n\n const userSessionRecordingOptions = this.instance.config.session_recording\n\n if (userSessionRecordingOptions.maskNetworkRequestFn) {\n networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest)\n }\n\n if (!networkRequest) {\n return\n }\n\n const eventJson = event.toJSON()\n eventJson.name = networkRequest.url\n const properties: { [key: number]: any } = {}\n // kudos to sentry javascript sdk for excellent background on why to use Date.now() here\n // https://github.com/getsentry/sentry-javascript/blob/e856e40b6e71a73252e788cd42b5260f81c9c88e/packages/utils/src/time.ts#L70\n // can't start observer if performance.now() is not available\n // eslint-disable-next-line compat/compat\n const timeOrigin = Math.floor(Date.now() - performance.now())\n properties[PERFORMANCE_EVENTS_MAPPING['timeOrigin']] = timeOrigin\n // clickhouse can't ingest timestamps that are floats\n // (in this case representing fractions of a millisecond we don't care about anyway)\n properties[PERFORMANCE_EVENTS_MAPPING['timestamp']] = Math.floor(timeOrigin + event.startTime)\n for (const key in PERFORMANCE_EVENTS_MAPPING) {\n if (!_isUndefined(eventJson[key])) {\n properties[PERFORMANCE_EVENTS_MAPPING[key]] = eventJson[key]\n }\n }\n\n this.capturePerformanceEvent(properties)\n\n if (exposesServerTiming(event)) {\n for (const timing of event.serverTiming || []) {\n this.capturePerformanceEvent({\n [PERFORMANCE_EVENTS_MAPPING['timeOrigin']]: timeOrigin,\n [PERFORMANCE_EVENTS_MAPPING['timestamp']]: Math.floor(timeOrigin + event.startTime),\n [PERFORMANCE_EVENTS_MAPPING['name']]: timing.name,\n [PERFORMANCE_EVENTS_MAPPING['duration']]: timing.duration,\n // the spec has a closed list of possible types\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/entryType\n // but, we need to know this was a server timing so that we know to\n // match it to the appropriate navigation or resource timing\n // that matching will have to be on timestamp and $current_url\n [PERFORMANCE_EVENTS_MAPPING['entryType']]: 'serverTiming',\n })\n }\n }\n }\n\n /**\n * :TRICKY: Make sure we batch these requests, and don't truncate the strings.\n */\n private capturePerformanceEvent(properties: { [key: number]: any }) {\n const timestamp = properties[PERFORMANCE_EVENTS_MAPPING['timestamp']]\n\n this.instance.sessionRecording?.onRRwebEmit({\n type: 6, // EventType.Plugin,\n data: {\n plugin: 'posthog/network@1',\n payload: properties,\n },\n timestamp,\n })\n\n // this.instance.capture('$performance_event', properties, {\n // transport: 'XHR',\n // method: 'POST',\n // endpoint: PERFORMANCE_INGESTION_ENDPOINT,\n // _noTruncate: true,\n // _batchKey: 'performanceEvent',\n // })\n }\n}\n\n/**\n * Check if this PerformanceEntry is either a PerformanceResourceTiming or a PerformanceNavigationTiming\n * NB PerformanceNavigationTiming extends PerformanceResourceTiming\n * Here we don't care which interface it implements as both expose `serverTimings`\n */\nconst exposesServerTiming = (event: PerformanceEntry): event is PerformanceResourceTiming =>\n event.entryType === 'navigation' || event.entryType === 'resource'\n"]}
@@ -1,3 +1,21 @@
1
+ /**
2
+ * Extend Segment with extra PostHog JS functionality. Required for things like Recordings and feature flags to work correctly.
3
+ *
4
+ * ### Usage
5
+ *
6
+ * ```js
7
+ * // After your standard segment anyalytics install
8
+ * analytics.load("GOEDfA21zZTtR7clsBuDvmBKAtAdZ6Np");
9
+ *
10
+ * analytics.ready(() => {
11
+ * posthog.init('<posthog-api-key>', {
12
+ * capture_pageview: false,
13
+ * segment: window.analytics, // NOTE: Be sure to use window.analytics here!
14
+ * });
15
+ * window.analytics.page();
16
+ * })
17
+ * ```
18
+ */
1
19
  import { PostHog } from '../posthog-core';
2
20
  interface SegmentPluginContext {
3
21
  event: {
@@ -1,22 +1,4 @@
1
- /**
2
- * Extend Segment with extra PostHog JS functionality. Required for things like Recordings and feature flags to work correctly.
3
- *
4
- * ### Usage
5
- *
6
- * ```js
7
- * // After your standard segment anyalytics install
8
- * analytics.load("GOEDfA21zZTtR7clsBuDvmBKAtAdZ6Np");
9
- *
10
- * analytics.ready(() => {
11
- * posthog.init('<posthog-api-key>', {
12
- * capture_pageview: false,
13
- * segment: window.analytics, // NOTE: Be sure to use window.analytics here!
14
- * });
15
- * window.analytics.page();
16
- * })
17
- * ```
18
- */
19
- import { logger } from '../utils';
1
+ import { logger } from '../utils/logger';
20
2
  export var createSegmentIntegration = function (posthog) {
21
3
  if (!Promise || !Promise.resolve) {
22
4
  logger.warn('This browser does not have Promise support, and can not use the segment integration');
@@ -1 +1 @@
1
- {"version":3,"file":"segment-integration.js","sourceRoot":"","sources":["../../../src/extensions/segment-integration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AA6BjC,MAAM,CAAC,IAAM,wBAAwB,GAAG,UAAC,OAAgB;IACrD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;QAC9B,MAAM,CAAC,IAAI,CAAC,qFAAqF,CAAC,CAAA;KACrG;IAED,IAAM,WAAW,GAAG,UAAC,GAAyB,EAAE,SAAiB;QAC7D,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,OAAO,CAAC,eAAe,EAAE,EAAE;YAC1E,wGAAwG;YACxG,OAAO,CAAC,KAAK,EAAE,CAAA;SAClB;QACD,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,EAAE;YACpE,OAAO,CAAC,QAAQ,CAAC;gBACb,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM;aAChC,CAAC,CAAA;YACF,OAAO,CAAC,kBAAkB,EAAE,CAAA;SAC/B;QAED,IAAM,oBAAoB,GAAG,OAAO,CAAC,2BAA2B,CAAC,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QACjG,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,oBAAoB,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QACpF,OAAO,GAAG,CAAA;IACd,CAAC,CAAA;IAED,OAAO;QACH,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,cAAM,OAAA,IAAI,EAAJ,CAAI;QACpB,+BAA+B;QAC/B,yCAAyC;QACzC,IAAI,EAAE,cAAM,OAAA,OAAO,CAAC,OAAO,EAAE,EAAjB,CAAiB;QAC7B,KAAK,EAAE,UAAC,GAAG,IAAK,OAAA,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAjC,CAAiC;QACjD,IAAI,EAAE,UAAC,GAAG,IAAK,OAAA,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,EAA7B,CAA6B;QAC5C,QAAQ,EAAE,UAAC,GAAG,IAAK,OAAA,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,EAA7B,CAA6B;QAChD,MAAM,EAAE,UAAC,GAAG,IAAK,OAAA,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,EAA3B,CAA2B;KAC/C,CAAA;AACL,CAAC,CAAA","sourcesContent":["/**\n * Extend Segment with extra PostHog JS functionality. Required for things like Recordings and feature flags to work correctly.\n *\n * ### Usage\n *\n * ```js\n * // After your standard segment anyalytics install\n * analytics.load(\"GOEDfA21zZTtR7clsBuDvmBKAtAdZ6Np\");\n *\n * analytics.ready(() => {\n * posthog.init('<posthog-api-key>', {\n * capture_pageview: false,\n * segment: window.analytics, // NOTE: Be sure to use window.analytics here!\n * });\n * window.analytics.page();\n * })\n * ```\n */\nimport { logger } from '../utils'\nimport { PostHog } from '../posthog-core'\n\n// Loosely based on https://github.com/segmentio/analytics-next/blob/master/packages/core/src/plugins/index.ts\ninterface SegmentPluginContext {\n event: {\n event: string\n userId?: string\n anonymousId?: string\n properties: any\n }\n}\n\ninterface SegmentPlugin {\n name: string\n version: string\n type: 'enrichment'\n isLoaded: () => boolean\n load: (ctx: SegmentPluginContext, instance: any, config?: any) => Promise<unknown>\n unload?: (ctx: SegmentPluginContext, instance: any) => Promise<unknown> | unknown\n ready?: () => Promise<unknown>\n track?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n identify?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n page?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n group?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n alias?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n screen?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n}\n\nexport const createSegmentIntegration = (posthog: PostHog): SegmentPlugin => {\n if (!Promise || !Promise.resolve) {\n logger.warn('This browser does not have Promise support, and can not use the segment integration')\n }\n\n const enrichEvent = (ctx: SegmentPluginContext, eventName: string) => {\n if (!ctx.event.userId && ctx.event.anonymousId !== posthog.get_distinct_id()) {\n // This is our only way of detecting that segment's analytics.reset() has been called so we also call it\n posthog.reset()\n }\n if (ctx.event.userId && ctx.event.userId !== posthog.get_distinct_id()) {\n posthog.register({\n distinct_id: ctx.event.userId,\n })\n posthog.reloadFeatureFlags()\n }\n\n const additionalProperties = posthog._calculate_event_properties(eventName, ctx.event.properties)\n ctx.event.properties = Object.assign({}, additionalProperties, ctx.event.properties)\n return ctx\n }\n\n return {\n name: 'PostHog JS',\n type: 'enrichment',\n version: '1.0.0',\n isLoaded: () => true,\n // check and early return above\n // eslint-disable-next-line compat/compat\n load: () => Promise.resolve(),\n track: (ctx) => enrichEvent(ctx, ctx.event.event),\n page: (ctx) => enrichEvent(ctx, '$pageview'),\n identify: (ctx) => enrichEvent(ctx, '$identify'),\n screen: (ctx) => enrichEvent(ctx, '$screen'),\n }\n}\n"]}
1
+ {"version":3,"file":"segment-integration.js","sourceRoot":"","sources":["../../../src/extensions/segment-integration.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AA4BxC,MAAM,CAAC,IAAM,wBAAwB,GAAG,UAAC,OAAgB;IACrD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;QAC9B,MAAM,CAAC,IAAI,CAAC,qFAAqF,CAAC,CAAA;KACrG;IAED,IAAM,WAAW,GAAG,UAAC,GAAyB,EAAE,SAAiB;QAC7D,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,OAAO,CAAC,eAAe,EAAE,EAAE;YAC1E,wGAAwG;YACxG,OAAO,CAAC,KAAK,EAAE,CAAA;SAClB;QACD,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,eAAe,EAAE,EAAE;YACpE,OAAO,CAAC,QAAQ,CAAC;gBACb,WAAW,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM;aAChC,CAAC,CAAA;YACF,OAAO,CAAC,kBAAkB,EAAE,CAAA;SAC/B;QAED,IAAM,oBAAoB,GAAG,OAAO,CAAC,2BAA2B,CAAC,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QACjG,GAAG,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,oBAAoB,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QACpF,OAAO,GAAG,CAAA;IACd,CAAC,CAAA;IAED,OAAO;QACH,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,cAAM,OAAA,IAAI,EAAJ,CAAI;QACpB,+BAA+B;QAC/B,yCAAyC;QACzC,IAAI,EAAE,cAAM,OAAA,OAAO,CAAC,OAAO,EAAE,EAAjB,CAAiB;QAC7B,KAAK,EAAE,UAAC,GAAG,IAAK,OAAA,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAjC,CAAiC;QACjD,IAAI,EAAE,UAAC,GAAG,IAAK,OAAA,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,EAA7B,CAA6B;QAC5C,QAAQ,EAAE,UAAC,GAAG,IAAK,OAAA,WAAW,CAAC,GAAG,EAAE,WAAW,CAAC,EAA7B,CAA6B;QAChD,MAAM,EAAE,UAAC,GAAG,IAAK,OAAA,WAAW,CAAC,GAAG,EAAE,SAAS,CAAC,EAA3B,CAA2B;KAC/C,CAAA;AACL,CAAC,CAAA","sourcesContent":["/**\n * Extend Segment with extra PostHog JS functionality. Required for things like Recordings and feature flags to work correctly.\n *\n * ### Usage\n *\n * ```js\n * // After your standard segment anyalytics install\n * analytics.load(\"GOEDfA21zZTtR7clsBuDvmBKAtAdZ6Np\");\n *\n * analytics.ready(() => {\n * posthog.init('<posthog-api-key>', {\n * capture_pageview: false,\n * segment: window.analytics, // NOTE: Be sure to use window.analytics here!\n * });\n * window.analytics.page();\n * })\n * ```\n */\nimport { PostHog } from '../posthog-core'\nimport { logger } from '../utils/logger'\n\n// Loosely based on https://github.com/segmentio/analytics-next/blob/master/packages/core/src/plugins/index.ts\ninterface SegmentPluginContext {\n event: {\n event: string\n userId?: string\n anonymousId?: string\n properties: any\n }\n}\n\ninterface SegmentPlugin {\n name: string\n version: string\n type: 'enrichment'\n isLoaded: () => boolean\n load: (ctx: SegmentPluginContext, instance: any, config?: any) => Promise<unknown>\n unload?: (ctx: SegmentPluginContext, instance: any) => Promise<unknown> | unknown\n ready?: () => Promise<unknown>\n track?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n identify?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n page?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n group?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n alias?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n screen?: (ctx: SegmentPluginContext) => Promise<SegmentPluginContext> | SegmentPluginContext\n}\n\nexport const createSegmentIntegration = (posthog: PostHog): SegmentPlugin => {\n if (!Promise || !Promise.resolve) {\n logger.warn('This browser does not have Promise support, and can not use the segment integration')\n }\n\n const enrichEvent = (ctx: SegmentPluginContext, eventName: string) => {\n if (!ctx.event.userId && ctx.event.anonymousId !== posthog.get_distinct_id()) {\n // This is our only way of detecting that segment's analytics.reset() has been called so we also call it\n posthog.reset()\n }\n if (ctx.event.userId && ctx.event.userId !== posthog.get_distinct_id()) {\n posthog.register({\n distinct_id: ctx.event.userId,\n })\n posthog.reloadFeatureFlags()\n }\n\n const additionalProperties = posthog._calculate_event_properties(eventName, ctx.event.properties)\n ctx.event.properties = Object.assign({}, additionalProperties, ctx.event.properties)\n return ctx\n }\n\n return {\n name: 'PostHog JS',\n type: 'enrichment',\n version: '1.0.0',\n isLoaded: () => true,\n // check and early return above\n // eslint-disable-next-line compat/compat\n load: () => Promise.resolve(),\n track: (ctx) => enrichEvent(ctx, ctx.event.event),\n page: (ctx) => enrichEvent(ctx, '$pageview'),\n identify: (ctx) => enrichEvent(ctx, '$identify'),\n screen: (ctx) => enrichEvent(ctx, '$screen'),\n }\n}\n"]}
@@ -20,9 +20,11 @@ var __rest = (this && this.__rest) || function (s, e) {
20
20
  }
21
21
  return t;
22
22
  };
23
- import { _register_event, _try, loadScript, logger, window } from '../utils';
23
+ import { _register_event, _try, loadScript } from '../utils';
24
24
  import { POSTHOG_MANAGED_HOSTS } from './cloud';
25
25
  import { _getHashParam } from '../utils/request-utils';
26
+ import { logger } from '../utils/logger';
27
+ import { window } from '../utils/globals';
26
28
  // TRICKY: Many web frameworks will modify the route on load, potentially before posthog is initialized.
27
29
  // To get ahead of this we grab it as soon as the posthog-js is parsed
28
30
  var STATE_FROM_WINDOW = window.location
@@ -1 +1 @@
1
- {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../../src/extensions/toolbar.ts"],"names":[],"mappings":"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","sourcesContent":["import { _register_event, _try, loadScript, logger, window } from '../utils'\nimport { PostHog } from '../posthog-core'\nimport { DecideResponse, ToolbarParams } from '../types'\nimport { POSTHOG_MANAGED_HOSTS } from './cloud'\nimport { _getHashParam } from '../utils/request-utils'\n\n// TRICKY: Many web frameworks will modify the route on load, potentially before posthog is initialized.\n// To get ahead of this we grab it as soon as the posthog-js is parsed\nconst STATE_FROM_WINDOW = window.location\n ? _getHashParam(window.location.hash, '__posthog') || _getHashParam(location.hash, 'state')\n : null\n\nexport class Toolbar {\n instance: PostHog\n constructor(instance: PostHog) {\n this.instance = instance\n }\n\n afterDecideResponse(response: DecideResponse) {\n const toolbarParams: ToolbarParams =\n response['toolbarParams'] ||\n response['editorParams'] ||\n (response['toolbarVersion'] ? { toolbarVersion: response['toolbarVersion'] } : {})\n if (\n response['isAuthenticated'] &&\n toolbarParams['toolbarVersion'] &&\n toolbarParams['toolbarVersion'].indexOf('toolbar') === 0\n ) {\n this.loadToolbar({\n ...toolbarParams,\n })\n }\n }\n\n /**\n * To load the toolbar, we need an access token and other state. That state comes from one of three places:\n * 1. In the URL hash params\n * 2. From session storage under the key `toolbarParams` if the toolbar was initialized on a previous page\n */\n maybeLoadToolbar(\n location = window.location,\n localStorage: Storage | undefined = undefined,\n history = window.history\n ): boolean {\n try {\n // Before running the code we check if we can access localStorage, if not we opt-out\n if (!localStorage) {\n try {\n window.localStorage.setItem('test', 'test')\n window.localStorage.removeItem('test')\n } catch (error) {\n return false\n }\n\n // If localStorage was undefined, and localStorage is supported we set the default value\n localStorage = window.localStorage\n }\n\n /**\n * Info about the state\n * The state is a json object\n * 1. (Legacy) The state can be `state={}` as a urlencoded object of info. In this case\n * 2. The state should now be found in `__posthog={}` and can be base64 encoded or urlencoded.\n * 3. Base64 encoding is preferred and will gradually be rolled out everywhere\n */\n\n const stateHash =\n STATE_FROM_WINDOW || _getHashParam(location.hash, '__posthog') || _getHashParam(location.hash, 'state')\n\n let toolbarParams: ToolbarParams\n const state = stateHash\n ? _try(() => JSON.parse(atob(decodeURIComponent(stateHash)))) ||\n _try(() => JSON.parse(decodeURIComponent(stateHash)))\n : null\n\n const parseFromUrl = state && state['action'] === 'ph_authorize'\n\n if (parseFromUrl) {\n // happens if they are initializing the toolbar using an old snippet\n toolbarParams = state\n toolbarParams.source = 'url'\n\n if (toolbarParams && Object.keys(toolbarParams).length > 0) {\n if (state['desiredHash']) {\n // hash that was in the url before the redirect\n location.hash = state['desiredHash']\n } else if (history) {\n history.replaceState('', document.title, location.pathname + location.search) // completely remove hash\n } else {\n location.hash = '' // clear hash (but leaves # unfortunately)\n }\n }\n } else {\n // get credentials from localStorage from a previous initialzation\n toolbarParams = JSON.parse(localStorage.getItem('_postHogToolbarParams') || '{}')\n toolbarParams.source = 'localstorage'\n\n // delete \"add-action\" or other intent from toolbarParams, otherwise we'll have the same intent\n // every time we open the page (e.g. you just visiting your own site an hour later)\n delete toolbarParams.userIntent\n }\n\n if (toolbarParams['token'] && this.instance.config.token === toolbarParams['token']) {\n this.loadToolbar(toolbarParams)\n return true\n } else {\n return false\n }\n } catch (e) {\n return false\n }\n }\n\n loadToolbar(params?: ToolbarParams): boolean {\n if ((window as any)['_postHogToolbarLoaded']) {\n return false\n }\n // only load the toolbar once, even if there are multiple instances of PostHogLib\n ;(window as any)['_postHogToolbarLoaded'] = true\n\n const host = this.instance.config.api_host\n // toolbar.js is served from the PostHog CDN, this has a TTL of 24 hours.\n // the toolbar asset includes a rotating \"token\" that is valid for 5 minutes.\n const fiveMinutesInMillis = 5 * 60 * 1000\n // this ensures that we bust the cache periodically\n const timestampToNearestFiveMinutes = Math.floor(Date.now() / fiveMinutesInMillis) * fiveMinutesInMillis\n const toolbarUrl = `${host}${host.endsWith('/') ? '' : '/'}static/toolbar.js?t=${timestampToNearestFiveMinutes}`\n const disableToolbarMetrics =\n !POSTHOG_MANAGED_HOSTS.includes(this.instance.config.api_host) &&\n this.instance.config.advanced_disable_toolbar_metrics\n\n const toolbarParams = {\n token: this.instance.config.token,\n ...params,\n apiURL: host, // defaults to api_host from the instance config if nothing else set\n ...(disableToolbarMetrics ? { instrument: false } : {}),\n }\n\n const { source: _discard, ...paramsToPersist } = toolbarParams // eslint-disable-line\n window.localStorage.setItem('_postHogToolbarParams', JSON.stringify(paramsToPersist))\n\n loadScript(toolbarUrl, (err) => {\n if (err) {\n logger.error('Failed to load toolbar', err)\n return\n }\n ;((window as any)['ph_load_toolbar'] || (window as any)['ph_load_editor'])(toolbarParams, this.instance)\n })\n // Turbolinks doesn't fire an onload event but does replace the entire body, including the toolbar.\n // Thus, we ensure the toolbar is only loaded inside the body, and then reloaded on turbolinks:load.\n _register_event(window, 'turbolinks:load', () => {\n ;(window as any)['_postHogToolbarLoaded'] = false\n this.loadToolbar(toolbarParams)\n })\n return true\n }\n\n /** @deprecated Use \"loadToolbar\" instead. */\n _loadEditor(params: ToolbarParams): boolean {\n return this.loadToolbar(params)\n }\n\n /** @deprecated Use \"maybeLoadToolbar\" instead. */\n maybeLoadEditor(\n location = window.location,\n localStorage: Storage | undefined = undefined,\n history = window.history\n ): boolean {\n return this.maybeLoadToolbar(location, localStorage, history)\n }\n}\n"]}
1
+ {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../../src/extensions/toolbar.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAG5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAEzC,wGAAwG;AACxG,sEAAsE;AACtE,IAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ;IACrC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAC3F,CAAC,CAAC,IAAI,CAAA;AAEV;IAEI,iBAAY,QAAiB;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC5B,CAAC;IAED,qCAAmB,GAAnB,UAAoB,QAAwB;QACxC,IAAM,aAAa,GACf,QAAQ,CAAC,eAAe,CAAC;YACzB,QAAQ,CAAC,cAAc,CAAC;YACxB,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACtF,IACI,QAAQ,CAAC,iBAAiB,CAAC;YAC3B,aAAa,CAAC,gBAAgB,CAAC;YAC/B,aAAa,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAC1D;YACE,IAAI,CAAC,WAAW,cACT,aAAa,EAClB,CAAA;SACL;IACL,CAAC;IAED;;;;OAIG;IACH,kCAAgB,GAAhB,UACI,QAA0B,EAC1B,YAA6C,EAC7C,OAAwB;QAFxB,yBAAA,EAAA,WAAW,MAAM,CAAC,QAAQ;QAC1B,6BAAA,EAAA,wBAA6C;QAC7C,wBAAA,EAAA,UAAU,MAAM,CAAC,OAAO;QAExB,IAAI;YACA,oFAAoF;YACpF,IAAI,CAAC,YAAY,EAAE;gBACf,IAAI;oBACA,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;oBAC3C,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;iBACzC;gBAAC,OAAO,KAAK,EAAE;oBACZ,OAAO,KAAK,CAAA;iBACf;gBAED,wFAAwF;gBACxF,YAAY,GAAG,MAAM,CAAC,YAAY,CAAA;aACrC;YAED;;;;;;eAMG;YAEH,IAAM,WAAS,GACX,iBAAiB,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,IAAI,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAE3G,IAAI,aAAa,SAAe,CAAA;YAChC,IAAM,KAAK,GAAG,WAAS;gBACnB,CAAC,CAAC,IAAI,CAAC,cAAM,OAAA,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,WAAS,CAAC,CAAC,CAAC,EAA/C,CAA+C,CAAC;oBAC3D,IAAI,CAAC,cAAM,OAAA,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,WAAS,CAAC,CAAC,EAAzC,CAAyC,CAAC;gBACvD,CAAC,CAAC,IAAI,CAAA;YAEV,IAAM,YAAY,GAAG,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,cAAc,CAAA;YAEhE,IAAI,YAAY,EAAE;gBACd,oEAAoE;gBACpE,aAAa,GAAG,KAAK,CAAA;gBACrB,aAAa,CAAC,MAAM,GAAG,KAAK,CAAA;gBAE5B,IAAI,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE;oBACxD,IAAI,KAAK,CAAC,aAAa,CAAC,EAAE;wBACtB,+CAA+C;wBAC/C,QAAQ,CAAC,IAAI,GAAG,KAAK,CAAC,aAAa,CAAC,CAAA;qBACvC;yBAAM,IAAI,OAAO,EAAE;wBAChB,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAA,CAAC,yBAAyB;qBAC1G;yBAAM;wBACH,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAA,CAAC,0CAA0C;qBAChE;iBACJ;aACJ;iBAAM;gBACH,kEAAkE;gBAClE,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,uBAAuB,CAAC,IAAI,IAAI,CAAC,CAAA;gBACjF,aAAa,CAAC,MAAM,GAAG,cAAc,CAAA;gBAErC,+FAA+F;gBAC/F,mFAAmF;gBACnF,OAAO,aAAa,CAAC,UAAU,CAAA;aAClC;YAED,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,KAAK,aAAa,CAAC,OAAO,CAAC,EAAE;gBACjF,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAA;gBAC/B,OAAO,IAAI,CAAA;aACd;iBAAM;gBACH,OAAO,KAAK,CAAA;aACf;SACJ;QAAC,OAAO,CAAC,EAAE;YACR,OAAO,KAAK,CAAA;SACf;IACL,CAAC;IAED,6BAAW,GAAX,UAAY,MAAsB;QAAlC,iBA0CC;QAzCG,IAAK,MAAc,CAAC,uBAAuB,CAAC,EAAE;YAC1C,OAAO,KAAK,CAAA;SACf;QACD,iFAAiF;QACjF,CAAC;QAAC,MAAc,CAAC,uBAAuB,CAAC,GAAG,IAAI,CAAA;QAEhD,IAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAA;QAC1C,yEAAyE;QACzE,6EAA6E;QAC7E,IAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;QACzC,mDAAmD;QACnD,IAAM,6BAA6B,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,mBAAmB,CAAC,GAAG,mBAAmB,CAAA;QACxG,IAAM,UAAU,GAAG,UAAG,IAAI,SAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,iCAAuB,6BAA6B,CAAE,CAAA;QAChH,IAAM,qBAAqB,GACvB,CAAC,qBAAqB,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;YAC9D,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,gCAAgC,CAAA;QAEzD,IAAM,aAAa,gCACf,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,IAC9B,MAAM,KACT,MAAM,EAAE,IAAI,KACT,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC1D,CAAA;QAEO,IAAQ,QAAQ,GAAyB,aAAa,OAAtC,EAAK,eAAe,UAAK,aAAa,EAAxD,UAAwC,CAAF,CAAkB,CAAC,sBAAsB;QACrF,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,uBAAuB,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAA;QAErF,UAAU,CAAC,UAAU,EAAE,UAAC,GAAG;YACvB,IAAI,GAAG,EAAE;gBACL,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,GAAG,CAAC,CAAA;gBAC3C,OAAM;aACT;YACD,CAAC;YAAA,CAAE,MAAc,CAAC,iBAAiB,CAAC,IAAK,MAAc,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,EAAE,KAAI,CAAC,QAAQ,CAAC,CAAA;QAC5G,CAAC,CAAC,CAAA;QACF,mGAAmG;QACnG,oGAAoG;QACpG,eAAe,CAAC,MAAM,EAAE,iBAAiB,EAAE;YACvC,CAAC;YAAC,MAAc,CAAC,uBAAuB,CAAC,GAAG,KAAK,CAAA;YACjD,KAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAA;QACnC,CAAC,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACf,CAAC;IAED,6CAA6C;IAC7C,6BAAW,GAAX,UAAY,MAAqB;QAC7B,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;IACnC,CAAC;IAED,kDAAkD;IAClD,iCAAe,GAAf,UACI,QAA0B,EAC1B,YAA6C,EAC7C,OAAwB;QAFxB,yBAAA,EAAA,WAAW,MAAM,CAAC,QAAQ;QAC1B,6BAAA,EAAA,wBAA6C;QAC7C,wBAAA,EAAA,UAAU,MAAM,CAAC,OAAO;QAExB,OAAO,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,CAAA;IACjE,CAAC;IACL,cAAC;AAAD,CAAC,AA9JD,IA8JC","sourcesContent":["import { _register_event, _try, loadScript } from '../utils'\nimport { PostHog } from '../posthog-core'\nimport { DecideResponse, ToolbarParams } from '../types'\nimport { POSTHOG_MANAGED_HOSTS } from './cloud'\nimport { _getHashParam } from '../utils/request-utils'\nimport { logger } from '../utils/logger'\nimport { window } from '../utils/globals'\n\n// TRICKY: Many web frameworks will modify the route on load, potentially before posthog is initialized.\n// To get ahead of this we grab it as soon as the posthog-js is parsed\nconst STATE_FROM_WINDOW = window.location\n ? _getHashParam(window.location.hash, '__posthog') || _getHashParam(location.hash, 'state')\n : null\n\nexport class Toolbar {\n instance: PostHog\n constructor(instance: PostHog) {\n this.instance = instance\n }\n\n afterDecideResponse(response: DecideResponse) {\n const toolbarParams: ToolbarParams =\n response['toolbarParams'] ||\n response['editorParams'] ||\n (response['toolbarVersion'] ? { toolbarVersion: response['toolbarVersion'] } : {})\n if (\n response['isAuthenticated'] &&\n toolbarParams['toolbarVersion'] &&\n toolbarParams['toolbarVersion'].indexOf('toolbar') === 0\n ) {\n this.loadToolbar({\n ...toolbarParams,\n })\n }\n }\n\n /**\n * To load the toolbar, we need an access token and other state. That state comes from one of three places:\n * 1. In the URL hash params\n * 2. From session storage under the key `toolbarParams` if the toolbar was initialized on a previous page\n */\n maybeLoadToolbar(\n location = window.location,\n localStorage: Storage | undefined = undefined,\n history = window.history\n ): boolean {\n try {\n // Before running the code we check if we can access localStorage, if not we opt-out\n if (!localStorage) {\n try {\n window.localStorage.setItem('test', 'test')\n window.localStorage.removeItem('test')\n } catch (error) {\n return false\n }\n\n // If localStorage was undefined, and localStorage is supported we set the default value\n localStorage = window.localStorage\n }\n\n /**\n * Info about the state\n * The state is a json object\n * 1. (Legacy) The state can be `state={}` as a urlencoded object of info. In this case\n * 2. The state should now be found in `__posthog={}` and can be base64 encoded or urlencoded.\n * 3. Base64 encoding is preferred and will gradually be rolled out everywhere\n */\n\n const stateHash =\n STATE_FROM_WINDOW || _getHashParam(location.hash, '__posthog') || _getHashParam(location.hash, 'state')\n\n let toolbarParams: ToolbarParams\n const state = stateHash\n ? _try(() => JSON.parse(atob(decodeURIComponent(stateHash)))) ||\n _try(() => JSON.parse(decodeURIComponent(stateHash)))\n : null\n\n const parseFromUrl = state && state['action'] === 'ph_authorize'\n\n if (parseFromUrl) {\n // happens if they are initializing the toolbar using an old snippet\n toolbarParams = state\n toolbarParams.source = 'url'\n\n if (toolbarParams && Object.keys(toolbarParams).length > 0) {\n if (state['desiredHash']) {\n // hash that was in the url before the redirect\n location.hash = state['desiredHash']\n } else if (history) {\n history.replaceState('', document.title, location.pathname + location.search) // completely remove hash\n } else {\n location.hash = '' // clear hash (but leaves # unfortunately)\n }\n }\n } else {\n // get credentials from localStorage from a previous initialzation\n toolbarParams = JSON.parse(localStorage.getItem('_postHogToolbarParams') || '{}')\n toolbarParams.source = 'localstorage'\n\n // delete \"add-action\" or other intent from toolbarParams, otherwise we'll have the same intent\n // every time we open the page (e.g. you just visiting your own site an hour later)\n delete toolbarParams.userIntent\n }\n\n if (toolbarParams['token'] && this.instance.config.token === toolbarParams['token']) {\n this.loadToolbar(toolbarParams)\n return true\n } else {\n return false\n }\n } catch (e) {\n return false\n }\n }\n\n loadToolbar(params?: ToolbarParams): boolean {\n if ((window as any)['_postHogToolbarLoaded']) {\n return false\n }\n // only load the toolbar once, even if there are multiple instances of PostHogLib\n ;(window as any)['_postHogToolbarLoaded'] = true\n\n const host = this.instance.config.api_host\n // toolbar.js is served from the PostHog CDN, this has a TTL of 24 hours.\n // the toolbar asset includes a rotating \"token\" that is valid for 5 minutes.\n const fiveMinutesInMillis = 5 * 60 * 1000\n // this ensures that we bust the cache periodically\n const timestampToNearestFiveMinutes = Math.floor(Date.now() / fiveMinutesInMillis) * fiveMinutesInMillis\n const toolbarUrl = `${host}${host.endsWith('/') ? '' : '/'}static/toolbar.js?t=${timestampToNearestFiveMinutes}`\n const disableToolbarMetrics =\n !POSTHOG_MANAGED_HOSTS.includes(this.instance.config.api_host) &&\n this.instance.config.advanced_disable_toolbar_metrics\n\n const toolbarParams = {\n token: this.instance.config.token,\n ...params,\n apiURL: host, // defaults to api_host from the instance config if nothing else set\n ...(disableToolbarMetrics ? { instrument: false } : {}),\n }\n\n const { source: _discard, ...paramsToPersist } = toolbarParams // eslint-disable-line\n window.localStorage.setItem('_postHogToolbarParams', JSON.stringify(paramsToPersist))\n\n loadScript(toolbarUrl, (err) => {\n if (err) {\n logger.error('Failed to load toolbar', err)\n return\n }\n ;((window as any)['ph_load_toolbar'] || (window as any)['ph_load_editor'])(toolbarParams, this.instance)\n })\n // Turbolinks doesn't fire an onload event but does replace the entire body, including the toolbar.\n // Thus, we ensure the toolbar is only loaded inside the body, and then reloaded on turbolinks:load.\n _register_event(window, 'turbolinks:load', () => {\n ;(window as any)['_postHogToolbarLoaded'] = false\n this.loadToolbar(toolbarParams)\n })\n return true\n }\n\n /** @deprecated Use \"loadToolbar\" instead. */\n _loadEditor(params: ToolbarParams): boolean {\n return this.loadToolbar(params)\n }\n\n /** @deprecated Use \"maybeLoadToolbar\" instead. */\n maybeLoadEditor(\n location = window.location,\n localStorage: Storage | undefined = undefined,\n history = window.history\n ): boolean {\n return this.maybeLoadToolbar(location, localStorage, history)\n }\n}\n"]}
@@ -10,9 +10,11 @@
10
10
  * This set of utilities is intended to enable opt in/out functionality in the PostHog JS SDK.
11
11
  * These functions are used internally by the SDK and are not intended to be publicly exposed.
12
12
  */
13
- import { _each, _includes, logger, window } from './utils';
13
+ import { _each, _includes } from './utils';
14
+ import { window } from './utils/globals';
14
15
  import { cookieStore, localStore, localPlusCookieStore } from './storage';
15
16
  import { _isNumber, _isString } from './utils/type-utils';
17
+ import { logger } from './utils/logger';
16
18
  /**
17
19
  * A function used to capture a PostHog event (e.g. PostHogLib.capture)
18
20
  * @callback captureFunction
@@ -1 +1 @@
1
- {"version":3,"file":"gdpr-utils.js","sourceRoot":"","sources":["../../src/gdpr-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAC1D,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAIzE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEzD;;;;;;GAMG;AAEH,cAAc;AAEd,IAAM,+BAA+B,GAAG,kBAAkB,CAAA;AAE1D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,OAAoB;IACrD,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;AACnC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,OAAoB;IACtD,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAA;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,OAAoB;IAC1D,OAAO,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAA;AACnD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,OAA6B;IACpE,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE;QAC/B,OAAO,IAAI,CAAA;KACd;IACD,OAAO,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,GAAG,CAAA;AACnD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa,EAAE,OAAoB;IAC7D,OAAO,GAAG,OAAO,IAAI,EAAE,CAAA;IACvB,WAAW,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAA;AAC/F,CAAC;AAED,eAAe;AAEf;;;;;GAKG;AACH,SAAS,WAAW,CAAC,OAAoB;IACrC,OAAO,GAAG,OAAO,IAAI,EAAE,CAAA;IACvB,IAAI,OAAO,CAAC,eAAe,KAAK,cAAc,EAAE;QAC5C,OAAO,UAAU,CAAA;KACpB;IACD,IAAI,OAAO,CAAC,eAAe,KAAK,qBAAqB,EAAE;QACnD,OAAO,oBAAoB,CAAA;KAC9B;IACD,OAAO,WAAW,CAAA;AACtB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,KAAa,EAAE,OAAoB;IACvD,OAAO,GAAG,OAAO,IAAI,EAAE,CAAA;IACvB,OAAO,CAAC,OAAO,CAAC,iBAAiB,IAAI,+BAA+B,CAAC,GAAG,KAAK,CAAA;AACjF,CAAC;AAED;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,KAAa,EAAE,OAAoB;IACzD,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAA;AACnE,CAAC;AAED;;;;;;GAMG;AACH,SAAS,oBAAoB,CAAC,OAAoB;IAC9C,IAAI,OAAO,IAAI,OAAO,CAAC,UAAU,EAAE;QAC/B,IAAM,GAAG,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAA;QACjD,IAAM,GAAG,GAAG,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAA;QAClC,IAAI,UAAQ,GAAG,KAAK,CAAA;QACpB,KAAK,CACD;YACI,GAAG,CAAC,YAAY,CAAC;YAChB,GAAW,CAAC,cAAc,CAAC;YAC3B,GAAW,CAAC,YAAY,CAAC;SAC7B,EACD,UAAU,QAAQ;YACd,IAAI,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,EAAE;gBAC5C,UAAQ,GAAG,IAAI,CAAA;aAClB;QACL,CAAC,CACJ,CAAA;QACD,OAAO,UAAQ,CAAA;KAClB;IACD,OAAO,KAAK,CAAA;AAChB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,SAAS,CAAC,QAAiB,EAAE,KAAa,EAAE,OAAoB;IACrE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;QACpC,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,+BAA+B,CAAC,CAAA;QACzF,OAAM;KACT;IAED,OAAO,GAAG,OAAO,IAAI,EAAE,CAAA;IAEvB,WAAW,CAAC,OAAO,CAAC,CAAC,GAAG,CACpB,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,EAC9B,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAChB,SAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,EACrE,OAAO,CAAC,oBAAoB,EAC5B,OAAO,CAAC,YAAY,CACvB,CAAA;IAED,IAAI,OAAO,CAAC,OAAO,IAAI,QAAQ,EAAE;QAC7B,kDAAkD;QAClD,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,IAAI,SAAS,EAAE,OAAO,CAAC,iBAAiB,IAAI,EAAE,EAAE;YACpF,cAAc,EAAE,IAAI;SACvB,CAAC,CAAA;KACL;AACL,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAgB;IACzC,IAAI,QAAQ,GAAG,KAAK,CAAA;IAEpB,IAAI;QACA,IAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAA;QAClC,IAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAA;QAC7C,IAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,kCAAkC,CAAA;QACzE,IAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,+BAA+B,IAAI,SAAS,CAAA;QACrF,IAAM,GAAG,GAAI,OAAO,CAAC,MAAc,CAAC,MAA4B,CAAA,CAAC,+CAA+C;QAEhH,IAAI,KAAK,EAAE;YACP,+EAA+E;YAC/E,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE;gBAC1B,UAAU,YAAA;gBACV,eAAe,iBAAA;gBACf,iBAAiB,mBAAA;gBACjB,MAAM,EAAE,GAAG;aACd,CAAC,CAAA;SACL;KACJ;IAAC,OAAO,GAAG,EAAE;QACV,MAAM,CAAC,KAAK,CAAC,2DAA2D,GAAG,GAAG,CAAC,CAAA;KAClF;IACD,OAAO,QAAQ,CAAA;AACnB,CAAC","sourcesContent":["/**\n * GDPR utils\n *\n * The General Data Protection Regulation (GDPR) is a regulation in EU law on data protection\n * and privacy for all individuals within the European Union. It addresses the export of personal\n * data outside the EU. The GDPR aims primarily to give control back to citizens and residents\n * over their personal data and to simplify the regulatory environment for international business\n * by unifying the regulation within the EU.\n *\n * This set of utilities is intended to enable opt in/out functionality in the PostHog JS SDK.\n * These functions are used internally by the SDK and are not intended to be publicly exposed.\n */\n\nimport { _each, _includes, logger, window } from './utils'\nimport { cookieStore, localStore, localPlusCookieStore } from './storage'\nimport { GDPROptions, PersistentStore } from './types'\nimport { PostHog } from './posthog-core'\n\nimport { _isNumber, _isString } from './utils/type-utils'\n\n/**\n * A function used to capture a PostHog event (e.g. PostHogLib.capture)\n * @callback captureFunction\n * @param {String} event_name The name of the event. This can be anything the user does - 'Button Click', 'Sign Up', 'Item Purchased', etc.\n * @param {Object} [properties] A set of properties to include with the event you're sending. These describe the user who did the event or details about the event itself.\n * @param {Function} [callback] If provided, the callback function will be called after capturing the event.\n */\n\n/** Public **/\n\nconst GDPR_DEFAULT_PERSISTENCE_PREFIX = '__ph_opt_in_out_'\n\n/**\n * Opt the user in to data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {captureFunction} [options.capture] - function used for capturing a PostHog event to record the opt-in action\n * @param {string} [options.captureEventName] - event name to be used for capturing the opt-in action\n * @param {Object} [options.captureProperties] - set of properties to be captured along with the opt-in action\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not\n */\nexport function optIn(token: string, options: GDPROptions): void {\n _optInOut(true, token, options)\n}\n\n/**\n * Opt the user out of data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-out cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-out cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-out cookie is set as secure or not\n */\nexport function optOut(token: string, options: GDPROptions): void {\n _optInOut(false, token, options)\n}\n\n/**\n * Check whether the user has opted in to data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @returns {boolean} whether the user has opted in to the given opt type\n */\nexport function hasOptedIn(token: string, options: GDPROptions): boolean {\n return _getStorageValue(token, options) === '1'\n}\n\n/**\n * Check whether the user has opted out of data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {boolean} [options.respectDnt] - flag to take browser DNT setting into account\n * @returns {boolean} whether the user has opted out of the given opt type\n */\nexport function hasOptedOut(token: string, options: Partial<GDPROptions>): boolean {\n if (_hasDoNotTrackFlagOn(options)) {\n return true\n }\n return _getStorageValue(token, options) === '0'\n}\n\n/**\n * Clear the user's opt in/out status of data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not\n */\nexport function clearOptInOut(token: string, options: GDPROptions) {\n options = options || {}\n _getStorage(options).remove(_getStorageKey(token, options), !!options.crossSubdomainCookie)\n}\n\n/** Private **/\n\n/**\n * Get storage util\n * @param {Object} [options]\n * @param {string} [options.persistenceType]\n * @returns {object} either cookieStore or localStore\n */\nfunction _getStorage(options: GDPROptions): PersistentStore {\n options = options || {}\n if (options.persistenceType === 'localStorage') {\n return localStore\n }\n if (options.persistenceType === 'localStorage+cookie') {\n return localPlusCookieStore\n }\n return cookieStore\n}\n\n/**\n * Get the name of the cookie that is used for the given opt type (capturing, cookie, etc.)\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @returns {string} the name of the cookie for the given opt type\n */\nfunction _getStorageKey(token: string, options: GDPROptions) {\n options = options || {}\n return (options.persistencePrefix || GDPR_DEFAULT_PERSISTENCE_PREFIX) + token\n}\n\n/**\n * Get the value of the cookie that is used for the given opt type (capturing, cookie, etc.)\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @returns {string} the value of the cookie for the given opt type\n */\nfunction _getStorageValue(token: string, options: GDPROptions) {\n return _getStorage(options).get(_getStorageKey(token, options))\n}\n\n/**\n * Check whether the user has set the DNT/doNotTrack setting to true in their browser\n * @param {Object} [options]\n * @param {string} [options.window] - alternate window object to check; used to force various DNT settings in browser tests\n * @param {boolean} [options.respectDnt] - flag to take browser DNT setting into account\n * @returns {boolean} whether the DNT setting is true\n */\nfunction _hasDoNotTrackFlagOn(options: GDPROptions) {\n if (options && options.respectDnt) {\n const win = (options && options.window) || window\n const nav = win['navigator'] || {}\n let hasDntOn = false\n _each(\n [\n nav['doNotTrack'], // standard\n (nav as any)['msDoNotTrack'],\n (win as any)['doNotTrack'],\n ],\n function (dntValue) {\n if (_includes([true, 1, '1', 'yes'], dntValue)) {\n hasDntOn = true\n }\n }\n )\n return hasDntOn\n }\n return false\n}\n\n/**\n * Set cookie/localstorage for the user indicating that they are opted in or out for the given opt type\n * @param {boolean} optValue - whether to opt the user in or out for the given opt type\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {captureFunction} [options.capture] - function used for capturing a PostHog event to record the opt-in action\n * @param {string} [options.captureEventName] - event name to be used for capturing the opt-in action\n * @param {Object} [options.captureProperties] - set of properties to be captured along with the opt-in action\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not\n */\nfunction _optInOut(optValue: boolean, token: string, options: GDPROptions) {\n if (!_isString(token) || !token.length) {\n logger.error('gdpr.' + (optValue ? 'optIn' : 'optOut') + ' called with an invalid token')\n return\n }\n\n options = options || {}\n\n _getStorage(options).set(\n _getStorageKey(token, options),\n optValue ? 1 : 0,\n _isNumber(options.cookieExpiration) ? options.cookieExpiration : null,\n options.crossSubdomainCookie,\n options.secureCookie\n )\n\n if (options.capture && optValue) {\n // only capture event if opting in (optValue=true)\n options.capture(options.captureEventName || '$opt_in', options.captureProperties || {}, {\n send_instantly: true,\n })\n }\n}\n\nexport function userOptedOut(posthog: PostHog) {\n let optedOut = false\n\n try {\n const token = posthog.config.token\n const respectDnt = posthog.config.respect_dnt\n const persistenceType = posthog.config.opt_out_capturing_persistence_type\n const persistencePrefix = posthog.config.opt_out_capturing_cookie_prefix || undefined\n const win = (posthog.config as any).window as Window | undefined // used to override window during browser tests\n\n if (token) {\n // if there was an issue getting the token, continue method execution as normal\n optedOut = hasOptedOut(token, {\n respectDnt,\n persistenceType,\n persistencePrefix,\n window: win,\n })\n }\n } catch (err) {\n logger.error('Unexpected error when checking capturing opt-out status: ' + err)\n }\n return optedOut\n}\n"]}
1
+ {"version":3,"file":"gdpr-utils.js","sourceRoot":"","sources":["../../src/gdpr-utils.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * GDPR utils\n *\n * The General Data Protection Regulation (GDPR) is a regulation in EU law on data protection\n * and privacy for all individuals within the European Union. It addresses the export of personal\n * data outside the EU. The GDPR aims primarily to give control back to citizens and residents\n * over their personal data and to simplify the regulatory environment for international business\n * by unifying the regulation within the EU.\n *\n * This set of utilities is intended to enable opt in/out functionality in the PostHog JS SDK.\n * These functions are used internally by the SDK and are not intended to be publicly exposed.\n */\n\nimport { _each, _includes } from './utils'\nimport { window } from './utils/globals'\nimport { cookieStore, localStore, localPlusCookieStore } from './storage'\nimport { GDPROptions, PersistentStore } from './types'\nimport { PostHog } from './posthog-core'\n\nimport { _isNumber, _isString } from './utils/type-utils'\nimport { logger } from './utils/logger'\n\n/**\n * A function used to capture a PostHog event (e.g. PostHogLib.capture)\n * @callback captureFunction\n * @param {String} event_name The name of the event. This can be anything the user does - 'Button Click', 'Sign Up', 'Item Purchased', etc.\n * @param {Object} [properties] A set of properties to include with the event you're sending. These describe the user who did the event or details about the event itself.\n * @param {Function} [callback] If provided, the callback function will be called after capturing the event.\n */\n\n/** Public **/\n\nconst GDPR_DEFAULT_PERSISTENCE_PREFIX = '__ph_opt_in_out_'\n\n/**\n * Opt the user in to data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {captureFunction} [options.capture] - function used for capturing a PostHog event to record the opt-in action\n * @param {string} [options.captureEventName] - event name to be used for capturing the opt-in action\n * @param {Object} [options.captureProperties] - set of properties to be captured along with the opt-in action\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not\n */\nexport function optIn(token: string, options: GDPROptions): void {\n _optInOut(true, token, options)\n}\n\n/**\n * Opt the user out of data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-out cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-out cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-out cookie is set as secure or not\n */\nexport function optOut(token: string, options: GDPROptions): void {\n _optInOut(false, token, options)\n}\n\n/**\n * Check whether the user has opted in to data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @returns {boolean} whether the user has opted in to the given opt type\n */\nexport function hasOptedIn(token: string, options: GDPROptions): boolean {\n return _getStorageValue(token, options) === '1'\n}\n\n/**\n * Check whether the user has opted out of data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {boolean} [options.respectDnt] - flag to take browser DNT setting into account\n * @returns {boolean} whether the user has opted out of the given opt type\n */\nexport function hasOptedOut(token: string, options: Partial<GDPROptions>): boolean {\n if (_hasDoNotTrackFlagOn(options)) {\n return true\n }\n return _getStorageValue(token, options) === '0'\n}\n\n/**\n * Clear the user's opt in/out status of data capturing and cookies/localstorage for the given token\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistenceType] Persistence mechanism used - cookie or localStorage\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not\n */\nexport function clearOptInOut(token: string, options: GDPROptions) {\n options = options || {}\n _getStorage(options).remove(_getStorageKey(token, options), !!options.crossSubdomainCookie)\n}\n\n/** Private **/\n\n/**\n * Get storage util\n * @param {Object} [options]\n * @param {string} [options.persistenceType]\n * @returns {object} either cookieStore or localStore\n */\nfunction _getStorage(options: GDPROptions): PersistentStore {\n options = options || {}\n if (options.persistenceType === 'localStorage') {\n return localStore\n }\n if (options.persistenceType === 'localStorage+cookie') {\n return localPlusCookieStore\n }\n return cookieStore\n}\n\n/**\n * Get the name of the cookie that is used for the given opt type (capturing, cookie, etc.)\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @returns {string} the name of the cookie for the given opt type\n */\nfunction _getStorageKey(token: string, options: GDPROptions) {\n options = options || {}\n return (options.persistencePrefix || GDPR_DEFAULT_PERSISTENCE_PREFIX) + token\n}\n\n/**\n * Get the value of the cookie that is used for the given opt type (capturing, cookie, etc.)\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @returns {string} the value of the cookie for the given opt type\n */\nfunction _getStorageValue(token: string, options: GDPROptions) {\n return _getStorage(options).get(_getStorageKey(token, options))\n}\n\n/**\n * Check whether the user has set the DNT/doNotTrack setting to true in their browser\n * @param {Object} [options]\n * @param {string} [options.window] - alternate window object to check; used to force various DNT settings in browser tests\n * @param {boolean} [options.respectDnt] - flag to take browser DNT setting into account\n * @returns {boolean} whether the DNT setting is true\n */\nfunction _hasDoNotTrackFlagOn(options: GDPROptions) {\n if (options && options.respectDnt) {\n const win = (options && options.window) || window\n const nav = win['navigator'] || {}\n let hasDntOn = false\n _each(\n [\n nav['doNotTrack'], // standard\n (nav as any)['msDoNotTrack'],\n (win as any)['doNotTrack'],\n ],\n function (dntValue) {\n if (_includes([true, 1, '1', 'yes'], dntValue)) {\n hasDntOn = true\n }\n }\n )\n return hasDntOn\n }\n return false\n}\n\n/**\n * Set cookie/localstorage for the user indicating that they are opted in or out for the given opt type\n * @param {boolean} optValue - whether to opt the user in or out for the given opt type\n * @param {string} token - PostHog project capturing token\n * @param {Object} [options]\n * @param {captureFunction} [options.capture] - function used for capturing a PostHog event to record the opt-in action\n * @param {string} [options.captureEventName] - event name to be used for capturing the opt-in action\n * @param {Object} [options.captureProperties] - set of properties to be captured along with the opt-in action\n * @param {string} [options.persistencePrefix=__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name\n * @param {Number} [options.cookieExpiration] - number of days until the opt-in cookie expires\n * @param {boolean} [options.crossSubdomainCookie] - whether the opt-in cookie is set as cross-subdomain or not\n * @param {boolean} [options.secureCookie] - whether the opt-in cookie is set as secure or not\n */\nfunction _optInOut(optValue: boolean, token: string, options: GDPROptions) {\n if (!_isString(token) || !token.length) {\n logger.error('gdpr.' + (optValue ? 'optIn' : 'optOut') + ' called with an invalid token')\n return\n }\n\n options = options || {}\n\n _getStorage(options).set(\n _getStorageKey(token, options),\n optValue ? 1 : 0,\n _isNumber(options.cookieExpiration) ? options.cookieExpiration : null,\n options.crossSubdomainCookie,\n options.secureCookie\n )\n\n if (options.capture && optValue) {\n // only capture event if opting in (optValue=true)\n options.capture(options.captureEventName || '$opt_in', options.captureProperties || {}, {\n send_instantly: true,\n })\n }\n}\n\nexport function userOptedOut(posthog: PostHog) {\n let optedOut = false\n\n try {\n const token = posthog.config.token\n const respectDnt = posthog.config.respect_dnt\n const persistenceType = posthog.config.opt_out_capturing_persistence_type\n const persistencePrefix = posthog.config.opt_out_capturing_cookie_prefix || undefined\n const win = (posthog.config as any).window as Window | undefined // used to override window during browser tests\n\n if (token) {\n // if there was an issue getting the token, continue method execution as normal\n optedOut = hasOptedOut(token, {\n respectDnt,\n persistenceType,\n persistencePrefix,\n window: win,\n })\n }\n } catch (err) {\n logger.error('Unexpected error when checking capturing opt-out status: ' + err)\n }\n return optedOut\n}\n"]}
@@ -9,7 +9,7 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
- import { window } from './utils';
12
+ import { window } from './utils/globals';
13
13
  var PageViewManager = /** @class */ (function () {
14
14
  function PageViewManager() {
15
15
  var _this = this;
@@ -1 +1 @@
1
- {"version":3,"file":"page-view.js","sourceRoot":"","sources":["../../src/page-view.ts"],"names":[],"mappings":"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","sourcesContent":["import { window } from './utils'\n\ninterface PageViewData {\n pathname: string\n // scroll is how far down the page the user has scrolled,\n // content is how far down the page the user can view content\n // (e.g. if the page is 1000 tall, but the user's screen is only 500 tall,\n // and they don't scroll at all, then scroll is 0 and content is 500)\n maxScrollHeight?: number\n maxScrollY?: number\n lastScrollY?: number\n maxContentHeight?: number\n maxContentY?: number\n lastContentY?: number\n}\n\ninterface ScrollProperties {\n $prev_pageview_last_scroll?: number\n $prev_pageview_last_scroll_percentage?: number\n $prev_pageview_max_scroll?: number\n $prev_pageview_max_scroll_percentage?: number\n $prev_pageview_last_content?: number\n $prev_pageview_last_content_percentage?: number\n $prev_pageview_max_content?: number\n $prev_pageview_max_content_percentage?: number\n}\n\ninterface PageViewEventProperties extends ScrollProperties {\n $prev_pageview_pathname?: string\n}\n\nexport class PageViewManager {\n _pageViewData: PageViewData | undefined\n _hasSeenPageView = false\n\n _createPageViewData(): PageViewData {\n return {\n pathname: window.location.pathname,\n }\n }\n\n doPageView(): PageViewEventProperties {\n let prevPageViewData: PageViewData | undefined\n // if there were events created before the first PageView, we would have created a\n // pageViewData for them. If this happened, we don't want to create a new pageViewData\n if (!this._hasSeenPageView) {\n this._hasSeenPageView = true\n prevPageViewData = undefined\n if (!this._pageViewData) {\n this._pageViewData = this._createPageViewData()\n }\n } else {\n prevPageViewData = this._pageViewData\n this._pageViewData = this._createPageViewData()\n }\n\n // update the scroll properties for the new page, but wait until the next tick\n // of the event loop\n setTimeout(this._updateScrollData, 0)\n\n return {\n $prev_pageview_pathname: prevPageViewData?.pathname,\n ...this._calculatePrevPageScrollProperties(prevPageViewData),\n }\n }\n\n doPageLeave(): PageViewEventProperties {\n const prevPageViewData = this._pageViewData\n return {\n $prev_pageview_pathname: prevPageViewData?.pathname,\n ...this._calculatePrevPageScrollProperties(prevPageViewData),\n }\n }\n\n _calculatePrevPageScrollProperties(prevPageViewData: PageViewData | undefined): ScrollProperties {\n if (\n !prevPageViewData ||\n prevPageViewData.maxScrollHeight == null ||\n prevPageViewData.lastScrollY == null ||\n prevPageViewData.maxScrollY == null ||\n prevPageViewData.maxContentHeight == null ||\n prevPageViewData.lastContentY == null ||\n prevPageViewData.maxContentY == null\n ) {\n return {}\n }\n\n let { maxScrollHeight, lastScrollY, maxScrollY, maxContentHeight, lastContentY, maxContentY } = prevPageViewData\n\n // Use ceil, so that e.g. scrolling 999.5px of a 1000px page is considered 100% scrolled\n maxScrollHeight = Math.ceil(maxScrollHeight)\n lastScrollY = Math.ceil(lastScrollY)\n maxScrollY = Math.ceil(maxScrollY)\n maxContentHeight = Math.ceil(maxContentHeight)\n lastContentY = Math.ceil(lastContentY)\n maxContentY = Math.ceil(maxContentY)\n\n // if the maximum scroll height is near 0, then the percentage is 1\n const lastScrollPercentage = maxScrollHeight <= 1 ? 1 : clamp(lastScrollY / maxScrollHeight, 0, 1)\n const maxScrollPercentage = maxScrollHeight <= 1 ? 1 : clamp(maxScrollY / maxScrollHeight, 0, 1)\n const lastContentPercentage = maxContentHeight <= 1 ? 1 : clamp(lastContentY / maxContentHeight, 0, 1)\n const maxContentPercentage = maxContentHeight <= 1 ? 1 : clamp(maxContentY / maxContentHeight, 0, 1)\n\n return {\n $prev_pageview_last_scroll: lastScrollY,\n $prev_pageview_last_scroll_percentage: lastScrollPercentage,\n $prev_pageview_max_scroll: maxScrollY,\n $prev_pageview_max_scroll_percentage: maxScrollPercentage,\n $prev_pageview_last_content: lastContentY,\n $prev_pageview_last_content_percentage: lastContentPercentage,\n $prev_pageview_max_content: maxContentY,\n $prev_pageview_max_content_percentage: maxContentPercentage,\n }\n }\n\n _updateScrollData = () => {\n if (!this._pageViewData) {\n this._pageViewData = this._createPageViewData()\n }\n const pageViewData = this._pageViewData\n\n const scrollY = this._scrollY()\n const scrollHeight = this._scrollHeight()\n const contentY = this._contentY()\n const contentHeight = this._contentHeight()\n\n pageViewData.lastScrollY = scrollY\n pageViewData.maxScrollY = Math.max(scrollY, pageViewData.maxScrollY ?? 0)\n pageViewData.maxScrollHeight = Math.max(scrollHeight, pageViewData.maxScrollHeight ?? 0)\n\n pageViewData.lastContentY = contentY\n pageViewData.maxContentY = Math.max(contentY, pageViewData.maxContentY ?? 0)\n pageViewData.maxContentHeight = Math.max(contentHeight, pageViewData.maxContentHeight ?? 0)\n }\n\n startMeasuringScrollPosition() {\n window.addEventListener('scroll', this._updateScrollData)\n window.addEventListener('scrollend', this._updateScrollData)\n window.addEventListener('resize', this._updateScrollData)\n }\n\n stopMeasuringScrollPosition() {\n window.removeEventListener('scroll', this._updateScrollData)\n window.removeEventListener('scrollend', this._updateScrollData)\n window.removeEventListener('resize', this._updateScrollData)\n }\n\n _scrollHeight(): number {\n return Math.max(0, window.document.documentElement.scrollHeight - window.document.documentElement.clientHeight)\n }\n\n _scrollY(): number {\n return window.scrollY || window.pageYOffset || window.document.documentElement.scrollTop || 0\n }\n\n _contentHeight(): number {\n return window.document.documentElement.scrollHeight || 0\n }\n\n _contentY(): number {\n const clientHeight = window.document.documentElement.clientHeight || 0\n return this._scrollY() + clientHeight\n }\n}\n\nfunction clamp(x: number, min: number, max: number) {\n return Math.max(min, Math.min(x, max))\n}\n"]}
1
+ {"version":3,"file":"page-view.js","sourceRoot":"","sources":["../../src/page-view.ts"],"names":[],"mappings":"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","sourcesContent":["import { window } from './utils/globals'\n\ninterface PageViewData {\n pathname: string\n // scroll is how far down the page the user has scrolled,\n // content is how far down the page the user can view content\n // (e.g. if the page is 1000 tall, but the user's screen is only 500 tall,\n // and they don't scroll at all, then scroll is 0 and content is 500)\n maxScrollHeight?: number\n maxScrollY?: number\n lastScrollY?: number\n maxContentHeight?: number\n maxContentY?: number\n lastContentY?: number\n}\n\ninterface ScrollProperties {\n $prev_pageview_last_scroll?: number\n $prev_pageview_last_scroll_percentage?: number\n $prev_pageview_max_scroll?: number\n $prev_pageview_max_scroll_percentage?: number\n $prev_pageview_last_content?: number\n $prev_pageview_last_content_percentage?: number\n $prev_pageview_max_content?: number\n $prev_pageview_max_content_percentage?: number\n}\n\ninterface PageViewEventProperties extends ScrollProperties {\n $prev_pageview_pathname?: string\n}\n\nexport class PageViewManager {\n _pageViewData: PageViewData | undefined\n _hasSeenPageView = false\n\n _createPageViewData(): PageViewData {\n return {\n pathname: window.location.pathname,\n }\n }\n\n doPageView(): PageViewEventProperties {\n let prevPageViewData: PageViewData | undefined\n // if there were events created before the first PageView, we would have created a\n // pageViewData for them. If this happened, we don't want to create a new pageViewData\n if (!this._hasSeenPageView) {\n this._hasSeenPageView = true\n prevPageViewData = undefined\n if (!this._pageViewData) {\n this._pageViewData = this._createPageViewData()\n }\n } else {\n prevPageViewData = this._pageViewData\n this._pageViewData = this._createPageViewData()\n }\n\n // update the scroll properties for the new page, but wait until the next tick\n // of the event loop\n setTimeout(this._updateScrollData, 0)\n\n return {\n $prev_pageview_pathname: prevPageViewData?.pathname,\n ...this._calculatePrevPageScrollProperties(prevPageViewData),\n }\n }\n\n doPageLeave(): PageViewEventProperties {\n const prevPageViewData = this._pageViewData\n return {\n $prev_pageview_pathname: prevPageViewData?.pathname,\n ...this._calculatePrevPageScrollProperties(prevPageViewData),\n }\n }\n\n _calculatePrevPageScrollProperties(prevPageViewData: PageViewData | undefined): ScrollProperties {\n if (\n !prevPageViewData ||\n prevPageViewData.maxScrollHeight == null ||\n prevPageViewData.lastScrollY == null ||\n prevPageViewData.maxScrollY == null ||\n prevPageViewData.maxContentHeight == null ||\n prevPageViewData.lastContentY == null ||\n prevPageViewData.maxContentY == null\n ) {\n return {}\n }\n\n let { maxScrollHeight, lastScrollY, maxScrollY, maxContentHeight, lastContentY, maxContentY } = prevPageViewData\n\n // Use ceil, so that e.g. scrolling 999.5px of a 1000px page is considered 100% scrolled\n maxScrollHeight = Math.ceil(maxScrollHeight)\n lastScrollY = Math.ceil(lastScrollY)\n maxScrollY = Math.ceil(maxScrollY)\n maxContentHeight = Math.ceil(maxContentHeight)\n lastContentY = Math.ceil(lastContentY)\n maxContentY = Math.ceil(maxContentY)\n\n // if the maximum scroll height is near 0, then the percentage is 1\n const lastScrollPercentage = maxScrollHeight <= 1 ? 1 : clamp(lastScrollY / maxScrollHeight, 0, 1)\n const maxScrollPercentage = maxScrollHeight <= 1 ? 1 : clamp(maxScrollY / maxScrollHeight, 0, 1)\n const lastContentPercentage = maxContentHeight <= 1 ? 1 : clamp(lastContentY / maxContentHeight, 0, 1)\n const maxContentPercentage = maxContentHeight <= 1 ? 1 : clamp(maxContentY / maxContentHeight, 0, 1)\n\n return {\n $prev_pageview_last_scroll: lastScrollY,\n $prev_pageview_last_scroll_percentage: lastScrollPercentage,\n $prev_pageview_max_scroll: maxScrollY,\n $prev_pageview_max_scroll_percentage: maxScrollPercentage,\n $prev_pageview_last_content: lastContentY,\n $prev_pageview_last_content_percentage: lastContentPercentage,\n $prev_pageview_max_content: maxContentY,\n $prev_pageview_max_content_percentage: maxContentPercentage,\n }\n }\n\n _updateScrollData = () => {\n if (!this._pageViewData) {\n this._pageViewData = this._createPageViewData()\n }\n const pageViewData = this._pageViewData\n\n const scrollY = this._scrollY()\n const scrollHeight = this._scrollHeight()\n const contentY = this._contentY()\n const contentHeight = this._contentHeight()\n\n pageViewData.lastScrollY = scrollY\n pageViewData.maxScrollY = Math.max(scrollY, pageViewData.maxScrollY ?? 0)\n pageViewData.maxScrollHeight = Math.max(scrollHeight, pageViewData.maxScrollHeight ?? 0)\n\n pageViewData.lastContentY = contentY\n pageViewData.maxContentY = Math.max(contentY, pageViewData.maxContentY ?? 0)\n pageViewData.maxContentHeight = Math.max(contentHeight, pageViewData.maxContentHeight ?? 0)\n }\n\n startMeasuringScrollPosition() {\n window.addEventListener('scroll', this._updateScrollData)\n window.addEventListener('scrollend', this._updateScrollData)\n window.addEventListener('resize', this._updateScrollData)\n }\n\n stopMeasuringScrollPosition() {\n window.removeEventListener('scroll', this._updateScrollData)\n window.removeEventListener('scrollend', this._updateScrollData)\n window.removeEventListener('resize', this._updateScrollData)\n }\n\n _scrollHeight(): number {\n return Math.max(0, window.document.documentElement.scrollHeight - window.document.documentElement.clientHeight)\n }\n\n _scrollY(): number {\n return window.scrollY || window.pageYOffset || window.document.documentElement.scrollTop || 0\n }\n\n _contentHeight(): number {\n return window.document.documentElement.scrollHeight || 0\n }\n\n _contentY(): number {\n const clientHeight = window.document.documentElement.clientHeight || 0\n return this._scrollY() + clientHeight\n }\n}\n\nfunction clamp(x: number, min: number, max: number) {\n return Math.max(min, Math.min(x, max))\n}\n"]}