@amplitude/analytics-core 2.45.0 → 2.47.0-sr-3531-rc-2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/index.d.ts +3 -1
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +4 -2
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/observers/video.d.ts +4 -0
- package/lib/cjs/observers/video.d.ts.map +1 -1
- package/lib/cjs/observers/video.js +32 -8
- package/lib/cjs/observers/video.js.map +1 -1
- package/lib/cjs/types/config/browser-config.d.ts +34 -1
- package/lib/cjs/types/config/browser-config.d.ts.map +1 -1
- package/lib/cjs/types/config/browser-config.js.map +1 -1
- package/lib/cjs/types/frustration-interactions.d.ts +0 -2
- package/lib/cjs/types/frustration-interactions.d.ts.map +1 -1
- package/lib/cjs/types/frustration-interactions.js.map +1 -1
- package/lib/cjs/types/performance-tracking.d.ts +37 -0
- package/lib/cjs/types/performance-tracking.d.ts.map +1 -0
- package/lib/cjs/types/performance-tracking.js +3 -0
- package/lib/cjs/types/performance-tracking.js.map +1 -0
- package/lib/cjs/utils/omit-undefined.d.ts +2 -0
- package/lib/cjs/utils/omit-undefined.d.ts.map +1 -0
- package/lib/cjs/utils/omit-undefined.js +15 -0
- package/lib/cjs/utils/omit-undefined.js.map +1 -0
- package/lib/cjs/video-analytics/track-video.d.ts.map +1 -1
- package/lib/cjs/video-analytics/track-video.js +48 -11
- package/lib/cjs/video-analytics/track-video.js.map +1 -1
- package/lib/cjs/video-analytics/types.d.ts +8 -2
- package/lib/cjs/video-analytics/types.d.ts.map +1 -1
- package/lib/cjs/video-analytics/types.js.map +1 -1
- package/lib/esm/index.d.ts +3 -1
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/observers/video.d.ts +4 -0
- package/lib/esm/observers/video.d.ts.map +1 -1
- package/lib/esm/observers/video.js +32 -8
- package/lib/esm/observers/video.js.map +1 -1
- package/lib/esm/types/config/browser-config.d.ts +34 -1
- package/lib/esm/types/config/browser-config.d.ts.map +1 -1
- package/lib/esm/types/config/browser-config.js.map +1 -1
- package/lib/esm/types/frustration-interactions.d.ts +0 -2
- package/lib/esm/types/frustration-interactions.d.ts.map +1 -1
- package/lib/esm/types/frustration-interactions.js.map +1 -1
- package/lib/esm/types/performance-tracking.d.ts +37 -0
- package/lib/esm/types/performance-tracking.d.ts.map +1 -0
- package/lib/esm/types/performance-tracking.js +2 -0
- package/lib/esm/types/performance-tracking.js.map +1 -0
- package/lib/esm/utils/omit-undefined.d.ts +2 -0
- package/lib/esm/utils/omit-undefined.d.ts.map +1 -0
- package/lib/esm/utils/omit-undefined.js +11 -0
- package/lib/esm/utils/omit-undefined.js.map +1 -0
- package/lib/esm/video-analytics/track-video.d.ts.map +1 -1
- package/lib/esm/video-analytics/track-video.js +48 -11
- package/lib/esm/video-analytics/track-video.js.map +1 -1
- package/lib/esm/video-analytics/types.d.ts +8 -2
- package/lib/esm/video-analytics/types.d.ts.map +1 -1
- package/lib/esm/video-analytics/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-config.js","sourceRoot":"","sources":["../../../../src/types/config/browser-config.ts"],"names":[],"mappings":"AA+PA,MAAM,CAAC,IAAM,qCAAqC,GAAG;IACnD,MAAM,EAAE,QAAQ;IAChB,eAAe,EAAE,iBAAiB;CAC1B,CAAC","sourcesContent":["import { UserSession } from '../user-session';\nimport { IdentityStorageType, Storage } from '../storage';\nimport { Transport, TransportTypeOrOptions } from '../transport';\nimport { IConfig } from './core-config';\nimport { ElementInteractionsOptions } from '../element-interactions';\nimport { FormInteractionsOptions } from '../form-interactions';\nimport { PageTrackingOptions } from '../page-view-tracking';\nimport { NetworkTrackingOptions } from '../network-tracking';\nimport { FrustrationInteractionsOptions } from '../frustration-interactions';\nimport { IDiagnosticsClient } from '../../diagnostics/diagnostics-client';\nimport { IRemoteConfigClient } from '../../remote-config/remote-config';\nimport { CustomEnrichmentOptions } from '../custom-enrichment';\n\nexport interface BrowserConfig extends ExternalBrowserConfig, InternalBrowserConfig {}\n\nexport interface ExternalBrowserConfig extends IConfig {\n /**\n * An app version for events tracked. This can be the version of your application.\n * @defaultValue `undefined`\n */\n appVersion?: string;\n /**\n * @deprecated This property is deprecated and will be removed in future versions. Please migrate to using `autocapture` instead.\n * The default event tracking configuration.\n * See {@link https://www.docs.developers.amplitude.com/data/sdks/browser-2/#tracking-default-events}.\n * @defaultValue `true`\n */\n defaultTracking?: boolean | DefaultTrackingOptions;\n /**\n * The configurations for auto-captured events.\n * See {@link https://www.docs.developers.amplitude.com/data/sdks/browser-2/autocapture/}.\n */\n autocapture?: boolean | AutocaptureOptions;\n /**\n * The configurations for custom enrichment.\n * @defaultValue `false`\n */\n customEnrichment?: boolean | CustomEnrichmentOptions;\n /**\n * The identifier for the device running your application.\n * @defaultValue `UUID()`\n */\n deviceId?: string;\n /**\n * Configuration for cookie.\n */\n cookieOptions?: CookieOptions;\n /**\n * The storage for user identify.\n * @defaultValue `\"cookie\"`\n */\n identityStorage?: IdentityStorageType;\n /**\n * The partner identifier.\n * Amplitude requires the customer who built an event ingestion integration to add the partner identifier to partner_id.\n * @defaultValue `undefined`\n */\n partnerId?: string;\n /**\n * The custom Session ID for the current session.\n * @defaultValue `timestamp`\n */\n sessionId?: number;\n /**\n * The period of inactivity from the last tracked event before a session expires in milliseconds.\n * @defaultValue `1,800,000` (30 minutes)\n */\n sessionTimeout: number;\n /**\n * The configurations for tracking additional properties.\n * See {@link https://www.docs.developers.amplitude.com/data/sdks/browser-2/#optional-tracking}.\n */\n trackingOptions: TrackingOptions;\n /**\n * Network transport mechanism used to send events.\n * @defaultValue `\"fetch\"`\n */\n transport?: TransportTypeOrOptions;\n /**\n * The identifier for the user being tracked.\n * @defaultValue `undefined`\n */\n userId?: string;\n /**\n * User's Nth instance of performing a default Page Viewed event within a session.\n * Used for landing page analysis.\n */\n pageCounter?: number;\n /**\n * Whether to fetch remote configuration. The remote configuration can be updated in the Amplitude platform here:\n * https://app.amplitude.com/data/amplitude/{your_org_name}/settings/autocapture\n * @defaultValue `true`\n * @deprecated This property is deprecated and will be removed in future versions. Please use `remoteConfig.fetchRemoteConfig` instead.\n */\n fetchRemoteConfig?: boolean;\n /**\n * Remote configuration options.\n * @defaultValue `undefined`\n */\n remoteConfig?: RemoteConfigOptions;\n /**\n * Captures network requests and responses.\n * @defaultValue `undefined`\n * @deprecated use autocapture.networkTracking instead\n */\n networkTrackingOptions?: NetworkTrackingOptions;\n /**\n * Whether to enable diagnostics.\n * @defaultValue `true`\n */\n enableDiagnostics?: boolean;\n}\n\ninterface InternalBrowserConfig {\n cookieStorage: Storage<UserSession>;\n lastEventTime?: number;\n lastEventId?: number;\n transportProvider: Transport;\n version?: string;\n diagnosticsSampleRate?: number;\n diagnosticsClient?: IDiagnosticsClient;\n remoteConfigClient?: IRemoteConfigClient;\n deferredSessionId?: number;\n topLevelDomain?: string;\n _enableRequestBodyCompressionExperimental?: boolean;\n}\n\n/**\n * @deprecated This interface is deprecated and will be removed in future versions. Please migrate to using `AutocaptureOptions` instead.\n */\nexport interface DefaultTrackingOptions {\n /**\n * Enables/disables marketing attribution tracking or config with detailed attribution options.\n * @defaultValue `true`\n */\n attribution?: boolean | AttributionOptions;\n /**\n * Enables/disables form downloads tracking.\n * @defaultValue `true`\n */\n fileDownloads?: boolean;\n /**\n * Enables/disables form interaction tracking or configures with detailed options.\n * @defaultValue `true`\n */\n formInteractions?: boolean | FormInteractionsOptions;\n /**\n * Enables/disables default page view tracking.\n * @defaultValue `true`\n */\n pageViews?: boolean | PageTrackingOptions;\n /**\n * Enables/disables session tracking.\n * @defaultValue `true`\n */\n sessions?: boolean;\n}\n\nexport interface AutocaptureOptions {\n /**\n * Enables/disables marketing attribution tracking or config with detailed attribution options.\n * @defaultValue `true`\n */\n attribution?: boolean | AttributionOptions;\n /**\n * Enables/disables form downloads tracking.\n * @defaultValue `true`\n */\n fileDownloads?: boolean;\n /**\n * Enables/disables form interaction tracking or configures with detailed options.\n * @defaultValue `true`\n */\n formInteractions?: boolean | FormInteractionsOptions;\n /**\n * Enables/disables default page view tracking.\n * @defaultValue `true`\n */\n pageViews?: boolean | PageTrackingOptions;\n /**\n * Enables/disables session tracking.\n * @defaultValue `true`\n */\n sessions?: boolean;\n /**\n * Enables/disables user interactions tracking.\n * @defaultValue `false`\n */\n elementInteractions?: boolean | ElementInteractionsOptions;\n /**\n * Enables/disables frustration interactions tracking.\n * @defaultValue `false`\n */\n frustrationInteractions?: boolean | FrustrationInteractionsOptions;\n /**\n * Enables/disables network request tracking or config with detailed network tracking options.\n * @defaultValue `false`\n */\n networkTracking?: boolean | NetworkTrackingOptions;\n /**\n * Enables/disables web vitals tracking.\n * @defaultValue `false`\n */\n webVitals?: boolean;\n /**\n * Enables/disables page url enrichment.\n * @defaultValue `true`\n * @experimental This feature is experimental and may not be stable\n */\n pageUrlEnrichment?: boolean;\n}\n\nexport interface TrackingOptions {\n /**\n * Enables/disables ip address tracking.\n * @defaultValue `true`\n */\n ipAddress?: boolean;\n /**\n * Enables/disables language tracking.\n * @defaultValue `true`\n */\n language?: boolean;\n /**\n * Enables/disables plantform tracking.\n * @defaultValue `true`\n */\n platform?: boolean;\n}\n\nexport interface AttributionOptions {\n /**\n * The rules to determine which referrers are excluded from being tracked as traffic source.\n * @defaultValue `[/your-domain\\.com$/]`\n */\n excludeReferrers?: (string | RegExp)[];\n /**\n * Exclude internal referrers from campaign attribution.\n * (a referrer is 'internal' if it is on the same domain as the current page)\n * @experimental this feature is experimental and may not be stable\n * @defaultValue `false`\n */\n excludeInternalReferrers?: true | false | ExcludeInternalReferrersOptions;\n /**\n * The value to represent undefined/no initial campaign parameter for first-touch attribution.\n * @defaultValue `\"EMPTY\"`\n */\n initialEmptyValue?: string;\n /**\n * The flag of if Amplitude to start a new session if any campaign parameter changes.\n * @defaultValue `false`\n */\n resetSessionOnNewCampaign?: boolean;\n}\n\nexport const EXCLUDE_INTERNAL_REFERRERS_CONDITIONS = {\n always: 'always',\n ifEmptyCampaign: 'ifEmptyCampaign',\n} as const;\n\ntype ExcludeInternalReferrersCondition =\n (typeof EXCLUDE_INTERNAL_REFERRERS_CONDITIONS)[keyof typeof EXCLUDE_INTERNAL_REFERRERS_CONDITIONS];\n\nexport interface ExcludeInternalReferrersOptions {\n /*\n * The condition on which to exclude internal referrers for campaign attribution.\n * @defaultValue `\"always\"`\n */\n condition?: ExcludeInternalReferrersCondition;\n}\n\nexport interface RemoteConfigOptions {\n /**\n * Whether to fetch remote configuration. The remote configuration can be updated in the Amplitude platform here:\n * https://app.amplitude.com/data/amplitude/{your_org_name}/settings/autocapture\n * @defaultValue `true`\n */\n fetchRemoteConfig?: boolean;\n /**\n * Custom server URL for remote configuration requests. If not provided, defaults to the standard\n * Amplitude remote config endpoint based on serverZone (US or EU).\n * Use this to proxy remote config requests through your own server.\n * @defaultValue `undefined` (uses standard Amplitude remote config endpoint)\n */\n serverUrl?: string;\n}\n\nexport interface CookieOptions {\n /**\n * The domain property of cookies created.\n * @defaultValue `Your top level domain`\n */\n domain?: string;\n /**\n * The expiration of cookies created in days.\n * @defaultValue `365`\n */\n expiration?: number;\n /**\n * How cookies are sent with cross-site requests.\n * @defaultValue `\"Lax\"`\n */\n sameSite?: 'Strict' | 'Lax' | 'None';\n /**\n * The flag of if send cookies over secure protocols.\n * @defaultValue `false`\n */\n secure?: boolean;\n /**\n * The flag of if upgrade the cookies created by maintenance Browser SDK.\n * @defaultValue `true`\n */\n upgrade?: boolean;\n}\n\ntype HiddenOptions = 'apiKey' | 'transportProvider' | 'requestMetadata' | '_enableRequestBodyCompressionExperimental';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface BrowserOptions extends Omit<Partial<ExternalBrowserConfig>, HiddenOptions> {}\n"]}
|
|
1
|
+
{"version":3,"file":"browser-config.js","sourceRoot":"","sources":["../../../../src/types/config/browser-config.ts"],"names":[],"mappings":"AAiSA,MAAM,CAAC,IAAM,qCAAqC,GAAG;IACnD,MAAM,EAAE,QAAQ;IAChB,eAAe,EAAE,iBAAiB;CAC1B,CAAC","sourcesContent":["import { UserSession } from '../user-session';\nimport { IdentityStorageType, Storage } from '../storage';\nimport { Transport, TransportTypeOrOptions } from '../transport';\nimport { IConfig } from './core-config';\nimport { ElementInteractionsOptions } from '../element-interactions';\nimport { FormInteractionsOptions } from '../form-interactions';\nimport { PageTrackingOptions } from '../page-view-tracking';\nimport { NetworkTrackingOptions } from '../network-tracking';\nimport { FrustrationInteractionsOptions } from '../frustration-interactions';\nimport { PerformanceTrackingOptions } from '../performance-tracking';\nimport { IDiagnosticsClient } from '../../diagnostics/diagnostics-client';\nimport { IRemoteConfigClient } from '../../remote-config/remote-config';\nimport { CustomEnrichmentOptions } from '../custom-enrichment';\n\nexport interface BrowserConfig extends ExternalBrowserConfig, InternalBrowserConfig {}\n\nexport interface ExternalBrowserConfig extends IConfig {\n /**\n * An app version for events tracked. This can be the version of your application.\n * @defaultValue `undefined`\n */\n appVersion?: string;\n /**\n * @deprecated This property is deprecated and will be removed in future versions. Please migrate to using `autocapture` instead.\n * The default event tracking configuration.\n * See {@link https://www.docs.developers.amplitude.com/data/sdks/browser-2/#tracking-default-events}.\n * @defaultValue `true`\n */\n defaultTracking?: boolean | DefaultTrackingOptions;\n /**\n * The configurations for auto-captured events.\n * See {@link https://www.docs.developers.amplitude.com/data/sdks/browser-2/autocapture/}.\n */\n autocapture?: boolean | AutocaptureOptions;\n /**\n * The configurations for custom enrichment.\n * @defaultValue `false`\n */\n customEnrichment?: boolean | CustomEnrichmentOptions;\n /**\n * The identifier for the device running your application.\n * @defaultValue `UUID()`\n */\n deviceId?: string;\n /**\n * Configuration for cookie.\n */\n cookieOptions?: CookieOptions;\n /**\n * The storage for user identify.\n * @defaultValue `\"cookie\"`\n */\n identityStorage?: IdentityStorageType;\n /**\n * The partner identifier.\n * Amplitude requires the customer who built an event ingestion integration to add the partner identifier to partner_id.\n * @defaultValue `undefined`\n */\n partnerId?: string;\n /**\n * The custom Session ID for the current session.\n * @defaultValue `timestamp`\n */\n sessionId?: number;\n /**\n * The period of inactivity from the last tracked event before a session expires in milliseconds.\n * @defaultValue `1,800,000` (30 minutes)\n */\n sessionTimeout: number;\n /**\n * The configurations for tracking additional properties.\n * See {@link https://www.docs.developers.amplitude.com/data/sdks/browser-2/#optional-tracking}.\n */\n trackingOptions: TrackingOptions;\n /**\n * Network transport mechanism used to send events.\n * @defaultValue `\"fetch\"`\n */\n transport?: TransportTypeOrOptions;\n /**\n * The identifier for the user being tracked.\n * @defaultValue `undefined`\n */\n userId?: string;\n /**\n * User's Nth instance of performing a default Page Viewed event within a session.\n * Used for landing page analysis.\n */\n pageCounter?: number;\n /**\n * Whether to fetch remote configuration. The remote configuration can be updated in the Amplitude platform here:\n * https://app.amplitude.com/data/amplitude/{your_org_name}/settings/autocapture\n * @defaultValue `true`\n * @deprecated This property is deprecated and will be removed in future versions. Please use `remoteConfig.fetchRemoteConfig` instead.\n */\n fetchRemoteConfig?: boolean;\n /**\n * Remote configuration options.\n * @defaultValue `undefined`\n */\n remoteConfig?: RemoteConfigOptions;\n /**\n * Captures network requests and responses.\n * @defaultValue `undefined`\n * @deprecated use autocapture.networkTracking instead\n */\n networkTrackingOptions?: NetworkTrackingOptions;\n /**\n * Whether to enable diagnostics.\n * @defaultValue `true`\n */\n enableDiagnostics?: boolean;\n}\n\ninterface InternalBrowserConfig {\n cookieStorage: Storage<UserSession>;\n lastEventTime?: number;\n lastEventId?: number;\n transportProvider: Transport;\n version?: string;\n diagnosticsSampleRate?: number;\n diagnosticsClient?: IDiagnosticsClient;\n remoteConfigClient?: IRemoteConfigClient;\n deferredSessionId?: number;\n topLevelDomain?: string;\n _enableRequestBodyCompressionExperimental?: boolean;\n}\n\n/**\n * @deprecated This interface is deprecated and will be removed in future versions. Please migrate to using `AutocaptureOptions` instead.\n */\nexport interface DefaultTrackingOptions {\n /**\n * Enables/disables marketing attribution tracking or config with detailed attribution options.\n * @defaultValue `true`\n */\n attribution?: boolean | AttributionOptions;\n /**\n * Enables/disables form downloads tracking.\n * @defaultValue `true`\n */\n fileDownloads?: boolean;\n /**\n * Enables/disables form interaction tracking or configures with detailed options.\n * @defaultValue `true`\n */\n formInteractions?: boolean | FormInteractionsOptions;\n /**\n * Enables/disables default page view tracking.\n * @defaultValue `true`\n */\n pageViews?: boolean | PageTrackingOptions;\n /**\n * Enables/disables session tracking.\n * @defaultValue `true`\n */\n sessions?: boolean;\n}\n\nexport interface AutocaptureOptions {\n /**\n * Enables/disables marketing attribution tracking or config with detailed attribution options.\n * @defaultValue `true`\n */\n attribution?: boolean | AttributionOptions;\n /**\n * Enables/disables form downloads tracking.\n * @defaultValue `true`\n */\n fileDownloads?: boolean;\n /**\n * Enables/disables form interaction tracking or configures with detailed options.\n * @defaultValue `true`\n */\n formInteractions?: boolean | FormInteractionsOptions;\n /**\n * Enables/disables default page view tracking.\n * @defaultValue `true`\n */\n pageViews?: boolean | PageTrackingOptions;\n /**\n * Enables/disables session tracking.\n * @defaultValue `true`\n */\n sessions?: boolean;\n /**\n * Enables/disables user interactions tracking.\n * @defaultValue `false`\n */\n elementInteractions?: boolean | ElementInteractionsOptions;\n /**\n * Enables/disables frustration interactions tracking.\n * @defaultValue `false`\n */\n frustrationInteractions?: boolean | FrustrationInteractionsOptions;\n /**\n * Enables/disables network request tracking or config with detailed network tracking options.\n * @defaultValue `false`\n */\n networkTracking?: boolean | NetworkTrackingOptions;\n /**\n * Enables/disables web vitals tracking.\n * @defaultValue `false`\n */\n webVitals?: boolean;\n /**\n * Enables/disables performance tracking.\n * @defaultValue `false`\n */\n performanceTracking?: boolean | PerformanceTrackingOptions;\n /**\n * Enables/disables page url enrichment.\n * @defaultValue `true`\n * @experimental This feature is experimental and may not be stable\n */\n pageUrlEnrichment?: boolean;\n}\n\nexport interface TrackingOptions {\n /**\n * Enables/disables ip address tracking.\n * @defaultValue `true`\n */\n ipAddress?: boolean;\n /**\n * Enables/disables language tracking.\n * @defaultValue `true`\n */\n language?: boolean;\n /**\n * Enables/disables plantform tracking.\n * @defaultValue `true`\n */\n platform?: boolean;\n}\n\nexport type TrackingMethod = 'userProperty' | 'eventProperty';\n\nexport interface AttributionOptions {\n /**\n * The rules to determine which referrers are excluded from being tracked as traffic source.\n * Applies only to `userProperty` tracking.\n * Ignored by `eventProperty` tracking.\n * @defaultValue `[/your-domain\\.com$/]`\n */\n excludeReferrers?: (string | RegExp)[];\n /**\n * Exclude internal referrers from campaign attribution.\n * (a referrer is 'internal' if it is on the same domain as the current page)\n * Applies only to `userProperty` tracking.\n * Ignored by `eventProperty` tracking.\n * @defaultValue `false`\n */\n excludeInternalReferrers?: true | false | ExcludeInternalReferrersOptions;\n /**\n * The value to represent undefined/no initial campaign parameter for first-touch attribution.\n * Applies only to `userProperty` tracking.\n * Ignored by `eventProperty` tracking.\n * @defaultValue `\"EMPTY\"`\n */\n initialEmptyValue?: string;\n /**\n * The flag of if Amplitude to start a new session if any campaign parameter changes.\n * Applies only to `userProperty` tracking.\n * Ignored by `eventProperty` tracking.\n * @defaultValue `false`\n */\n resetSessionOnNewCampaign?: boolean;\n /**\n * The attribution persistence strategy for campaign parameters.\n * Provide a single method to enable one strategy, or an array to enable multiple methods at the same time.\n * When multiple methods are provided, each enabled method runs independently and their behaviors are combined.\n * For example, `['userProperty', 'eventProperty']` updates user properties and also attaches campaign params\n * to event properties.\n * @experimental this feature is experimental and may not be stable\n * @defaultValue `\"userProperty\"`\n */\n trackingMethod?: TrackingMethod | TrackingMethod[];\n /**\n * Fires an `[Amplitude] Attribution` event as a heartbeat on every page view,\n * such as on page load and SPA URL changes.\n * Applies only to `eventProperty` tracking.\n * Ignored by `userProperty` tracking.\n * @experimental this feature is experimental and may not be stable\n * @defaultValue `false`\n */\n fallbackAttributionEvent?: boolean;\n}\n\nexport const EXCLUDE_INTERNAL_REFERRERS_CONDITIONS = {\n always: 'always',\n ifEmptyCampaign: 'ifEmptyCampaign',\n} as const;\n\ntype ExcludeInternalReferrersCondition =\n (typeof EXCLUDE_INTERNAL_REFERRERS_CONDITIONS)[keyof typeof EXCLUDE_INTERNAL_REFERRERS_CONDITIONS];\n\nexport interface ExcludeInternalReferrersOptions {\n /*\n * The condition on which to exclude internal referrers for campaign attribution.\n * @defaultValue `\"always\"`\n */\n condition?: ExcludeInternalReferrersCondition;\n}\n\nexport interface RemoteConfigOptions {\n /**\n * Whether to fetch remote configuration. The remote configuration can be updated in the Amplitude platform here:\n * https://app.amplitude.com/data/amplitude/{your_org_name}/settings/autocapture\n * @defaultValue `true`\n */\n fetchRemoteConfig?: boolean;\n /**\n * Custom server URL for remote configuration requests. If not provided, defaults to the standard\n * Amplitude remote config endpoint based on serverZone (US or EU).\n * Use this to proxy remote config requests through your own server.\n * @defaultValue `undefined` (uses standard Amplitude remote config endpoint)\n */\n serverUrl?: string;\n}\n\nexport interface CookieOptions {\n /**\n * The domain property of cookies created.\n * @defaultValue `Your top level domain`\n */\n domain?: string;\n /**\n * The expiration of cookies created in days.\n * @defaultValue `365`\n */\n expiration?: number;\n /**\n * How cookies are sent with cross-site requests.\n * @defaultValue `\"Lax\"`\n */\n sameSite?: 'Strict' | 'Lax' | 'None';\n /**\n * The flag of if send cookies over secure protocols.\n * @defaultValue `false`\n */\n secure?: boolean;\n /**\n * The flag of if upgrade the cookies created by maintenance Browser SDK.\n * @defaultValue `true`\n */\n upgrade?: boolean;\n}\n\ntype HiddenOptions = 'apiKey' | 'transportProvider' | 'requestMetadata' | '_enableRequestBodyCompressionExperimental';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface BrowserOptions extends Omit<Partial<ExternalBrowserConfig>, HiddenOptions> {}\n"]}
|
|
@@ -98,7 +98,6 @@ export interface FrustrationInteractionsOptions {
|
|
|
98
98
|
* Set to `false` to disable error click tracking.
|
|
99
99
|
* Set to `true` or an options object to enable with default settings.
|
|
100
100
|
* Default is false.
|
|
101
|
-
* @experimental this feature is experimental and may not be stable
|
|
102
101
|
*/
|
|
103
102
|
errorClicks?: boolean | ErrorClickOptions;
|
|
104
103
|
/**
|
|
@@ -106,7 +105,6 @@ export interface FrustrationInteractionsOptions {
|
|
|
106
105
|
* Set to `false` to disable thrashed cursor tracking.
|
|
107
106
|
* Set to `true` or an options object to enable with default settings.
|
|
108
107
|
* Default is false.
|
|
109
|
-
* @experimental this feature is experimental and may not be stable
|
|
110
108
|
*/
|
|
111
109
|
thrashedCursor?: boolean | ThrashedCursorOptions;
|
|
112
110
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frustration-interactions.d.ts","sourceRoot":"","sources":["../../../src/types/frustration-interactions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEvC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEzC;;;;;;;OAOG;IACH,wBAAwB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC;IAEpF;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;IAExC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;IAExC
|
|
1
|
+
{"version":3,"file":"frustration-interactions.d.ts","sourceRoot":"","sources":["../../../src/types/frustration-interactions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEvC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEzC;;;;;;;OAOG;IACH,wBAAwB,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,KAAK,OAAO,CAAC;IAEpF;;;OAGG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;IAExC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;IAExC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC;IAC1C;;;;;OAKG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,qBAAqB,CAAC;IAEjD;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,MAAM,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CACvE;AAyBD;;GAEG;AACH,eAAO,MAAM,4BAA4B,UAAyC,CAAC;AAEnF;;GAEG;AACH,eAAO,MAAM,6BAA6B,UAAyC,CAAC;AAEpF;;GAEG;AACH,eAAO,MAAM,4BAA4B,UAAQ,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,4BAA4B,OAAQ,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,0CAA0C,KAAK,CAAC;AAK7D,KAAK,UAAU,GAAG,OAAO,UAAU,SAAS;IAC1C,OAAO,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,KAAK,MAAM,CAAC,CAAC;CACxC,GACG,CAAC,GACD,KAAK,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frustration-interactions.js","sourceRoot":"","sources":["../../../src/types/frustration-interactions.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"frustration-interactions.js","sourceRoot":"","sources":["../../../src/types/frustration-interactions.ts"],"names":[],"mappings":";AA+HA,IAAM,2BAA2B,GAAG;IAClC,GAAG;IACH,QAAQ;IACR,iBAAiB;IACjB,eAAe;IACf,mBAAmB;IACnB,2BAA2B;IAC3B,wBAAwB;IACxB,iBAAiB;IACjB,cAAc;IACd,mBAAmB;IACnB,4BAA4B;CAC7B,CAAC;AAEF,IAAM,sCAAsC;IAC1C,sBAAsB;IACtB,sBAAsB;IACtB,qBAAqB;IACrB,qBAAqB;IACrB,oBAAoB;UACjB,2BAA2B,SAC/B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,IAAM,4BAA4B,GAAG,sCAAsC,CAAC;AAEnF;;GAEG;AACH,MAAM,CAAC,IAAM,6BAA6B,GAAG,sCAAsC,CAAC;AAEpF;;GAEG;AACH,MAAM,CAAC,IAAM,4BAA4B,GAAG,CAAC,GAAG,CAAC,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,IAAM,4BAA4B,GAAG,IAAK,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,IAAM,4BAA4B,GAAG,IAAK,CAAC;AAElD;;GAEG;AACH,MAAM,CAAC,IAAM,4BAA4B,GAAG,CAAC,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,IAAM,0CAA0C,GAAG,EAAE,CAAC,CAAC,SAAS","sourcesContent":["import { ActionType } from './element-interactions';\n\n/**\n * Configuration options for dead clicks tracking\n */\nexport interface DeadClickOptions {\n /**\n * CSS selectors to define which elements on the page to track for dead clicks.\n * A dead click is a click that doesn't result in any visible change or navigation.\n */\n cssSelectorAllowlist?: string[];\n}\n\n/**\n * Configuration options for rage clicks tracking\n */\nexport interface RageClickOptions {\n /**\n * CSS selectors to define which elements on the page to track for rage clicks.\n * A rage click is multiple rapid clicks on the same element within a 3s time window.\n */\n cssSelectorAllowlist?: string[];\n}\n\n/**\n * Configuration options for thrashed cursor tracking\n */\nexport interface ThrashedCursorOptions {\n /**\n * Number of direction changes required to consider a thrashed cursor.\n * Minimum of 5\n * (x axis changes and y axis changes are counted separately)\n * @default 20\n */\n directionChanges?: number;\n /**\n * Time window in milliseconds to consider a thrashed cursor.\n * Maximum of of 4000\n * @default 2000\n */\n threshold?: number;\n}\n\n/**\n * Configuration options for error clicks tracking\n */\nexport interface ErrorClickOptions {\n /**\n * CSS selectors to define which elements on the page to track for error clicks.\n * An error click is a click that results in an error.\n */\n cssSelectorAllowlist?: string[];\n}\n\n/**\n * Configuration options for frustration interactions tracking.\n * This includes dead clicks and rage clicks tracking.\n */\nexport interface FrustrationInteractionsOptions {\n /**\n * List of page URLs to allow auto tracking on.\n * When provided, only allow tracking on these URLs.\n * Both full URLs and regex are supported.\n */\n pageUrlAllowlist?: (string | RegExp)[];\n\n /**\n * List of page URLs to exclude from auto tracking.\n * When provided, tracking will be blocked on these URLs.\n * Both full URLs and regex are supported.\n * This takes precedence over pageUrlAllowlist.\n */\n pageUrlExcludelist?: (string | RegExp)[];\n\n /**\n * Function to determine whether an event should be tracked.\n * When provided, this function overwrites all other allowlists and configurations.\n * If the function returns true, the event will be tracked.\n * If the function returns false, the event will not be tracked.\n * @param actionType - The type of action that triggered the event.\n * @param element - The [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) that triggered the event.\n */\n shouldTrackEventResolver?: (actionType: ActionType, element: DomElement) => boolean;\n\n /**\n * Prefix for data attributes to allow auto collecting.\n * Default is 'data-amp-track-'.\n */\n dataAttributePrefix?: string;\n\n /**\n * Configuration for dead clicks tracking.\n * Set to `false` to disable dead click tracking.\n * Set to `true` or an options object to enable with default or custom settings.\n * Default is false.\n */\n deadClicks?: boolean | DeadClickOptions;\n\n /**\n * Configuration for rage clicks tracking.\n * Set to `false` to disable rage click tracking.\n * Set to `true` or an options object to enable with default settings.\n * Default is false.\n */\n rageClicks?: boolean | RageClickOptions;\n\n /**\n * Configuration for error clicks tracking\n * Set to `false` to disable error click tracking.\n * Set to `true` or an options object to enable with default settings.\n * Default is false.\n */\n errorClicks?: boolean | ErrorClickOptions;\n /**\n * Configuration for thrashed cursor tracking.\n * Set to `false` to disable thrashed cursor tracking.\n * Set to `true` or an options object to enable with default settings.\n * Default is false.\n */\n thrashedCursor?: boolean | ThrashedCursorOptions;\n\n /**\n * RegExp pattern list to allow custom patterns for text masking\n */\n maskTextRegex?: (RegExp | { pattern: string; description: string })[];\n}\n\nconst CLICKABLE_ELEMENT_SELECTORS = [\n 'a',\n 'button',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"menuitem\"]',\n '[role=\"menuitemcheckbox\"]',\n '[role=\"menuitemradio\"]',\n '[role=\"option\"]',\n '[role=\"tab\"]',\n '[role=\"treeitem\"]',\n '[contenteditable=\"true\" i]',\n];\n\nconst DEFAULT_ERROR_AND_DEAD_CLICK_ALLOWLIST = [\n 'input[type=\"button\"]',\n 'input[type=\"submit\"]',\n 'input[type=\"reset\"]',\n 'input[type=\"image\"]',\n 'input[type=\"file\"]',\n ...CLICKABLE_ELEMENT_SELECTORS,\n];\n\n/**\n * Default CSS selectors for dead clicks tracking\n */\nexport const DEFAULT_DEAD_CLICK_ALLOWLIST = DEFAULT_ERROR_AND_DEAD_CLICK_ALLOWLIST;\n\n/**\n * Default CSS selectors for error tracking\n */\nexport const DEFAULT_ERROR_CLICK_ALLOWLIST = DEFAULT_ERROR_AND_DEAD_CLICK_ALLOWLIST;\n\n/**\n * Default CSS selectors for rage clicks tracking\n */\nexport const DEFAULT_RAGE_CLICK_ALLOWLIST = ['*'];\n\n/**\n * Default time window for dead clicks (3 seconds)\n */\nexport const DEFAULT_DEAD_CLICK_WINDOW_MS = 3_000;\n\n/**\n * Default time window for rage clicks (1 second)\n */\nexport const DEFAULT_RAGE_CLICK_WINDOW_MS = 1_000;\n\n/**\n * Default threshold for rage clicks (4 clicks)\n */\nexport const DEFAULT_RAGE_CLICK_THRESHOLD = 4;\n\n/**\n * Default threshold for rage clicks to be considered out of bounds (50 pixels)\n */\nexport const DEFAULT_RAGE_CLICK_OUT_OF_BOUNDS_THRESHOLD = 50; // pixels\n\n// DomElement is [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) if the dom library is included in tsconfig.json\n// and never if it is not included\n// eslint-disable-next-line no-restricted-globals\ntype DomElement = typeof globalThis extends {\n Element: new (...args: any) => infer T;\n}\n ? T\n : never;\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for main thread block tracking
|
|
3
|
+
*/
|
|
4
|
+
export interface MainThreadBlockOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Minimum duration in milliseconds to consider a main thread block.
|
|
7
|
+
* @default 100
|
|
8
|
+
*/
|
|
9
|
+
durationThreshold?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Configuration options for performance tracking.
|
|
13
|
+
*/
|
|
14
|
+
export interface PerformanceTrackingOptions {
|
|
15
|
+
/**
|
|
16
|
+
* List of page URLs to allow auto tracking on.
|
|
17
|
+
* When provided, only allow tracking on these URLs.
|
|
18
|
+
* Both full URLs and regex are supported.
|
|
19
|
+
*/
|
|
20
|
+
pageUrlAllowlist?: (string | RegExp)[];
|
|
21
|
+
/**
|
|
22
|
+
* List of page URLs to exclude from auto tracking.
|
|
23
|
+
* When provided, tracking will be blocked on these URLs.
|
|
24
|
+
* Both full URLs and regex are supported.
|
|
25
|
+
* This takes precedence over pageUrlAllowlist.
|
|
26
|
+
*/
|
|
27
|
+
pageUrlExcludelist?: (string | RegExp)[];
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for main thread block tracking.
|
|
30
|
+
* Uses the Long Animation Frames API where available, falling back to Long Tasks.
|
|
31
|
+
* Set to `false` to disable tracking.
|
|
32
|
+
* Set to `true` or an options object to enable with default or custom settings.
|
|
33
|
+
* Default is false.
|
|
34
|
+
*/
|
|
35
|
+
mainThreadBlock?: boolean | MainThreadBlockOptions;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=performance-tracking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance-tracking.d.ts","sourceRoot":"","sources":["../../../src/types/performance-tracking.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEvC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEzC;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,OAAO,GAAG,sBAAsB,CAAC;CACpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"performance-tracking.js","sourceRoot":"","sources":["../../../src/types/performance-tracking.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Configuration options for main thread block tracking\n */\nexport interface MainThreadBlockOptions {\n /**\n * Minimum duration in milliseconds to consider a main thread block.\n * @default 100\n */\n durationThreshold?: number;\n}\n\n/**\n * Configuration options for performance tracking.\n */\nexport interface PerformanceTrackingOptions {\n /**\n * List of page URLs to allow auto tracking on.\n * When provided, only allow tracking on these URLs.\n * Both full URLs and regex are supported.\n */\n pageUrlAllowlist?: (string | RegExp)[];\n\n /**\n * List of page URLs to exclude from auto tracking.\n * When provided, tracking will be blocked on these URLs.\n * Both full URLs and regex are supported.\n * This takes precedence over pageUrlAllowlist.\n */\n pageUrlExcludelist?: (string | RegExp)[];\n\n /**\n * Configuration for main thread block tracking.\n * Uses the Long Animation Frames API where available, falling back to Long Tasks.\n * Set to `false` to disable tracking.\n * Set to `true` or an options object to enable with default or custom settings.\n * Default is false.\n */\n mainThreadBlock?: boolean | MainThreadBlockOptions;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"omit-undefined.d.ts","sourceRoot":"","sources":["../../../src/utils/omit-undefined.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,UAAW,OAAO,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,2BAStE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"omit-undefined.js","sourceRoot":"","sources":["../../../src/utils/omit-undefined.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,aAAa,GAAG,UAAC,KAAyC;IACrE,IAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,IAAM,GAAG,IAAI,KAAK,EAAE;QACvB,IAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,GAAG,EAAE;YACP,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;SAChB;KACF;IACD,OAAO,GAAG,CAAC;AACb,CAAC,CAAC","sourcesContent":["export const omitUndefined = (input: Record<string, string | undefined>) => {\n const obj: Record<string, string> = {};\n for (const key in input) {\n const val = input[key];\n if (val) {\n obj[key] = val;\n }\n }\n return obj;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-video.d.ts","sourceRoot":"","sources":["../../../src/video-analytics/track-video.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"track-video.d.ts","sourceRoot":"","sources":["../../../src/video-analytics/track-video.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,mBAAmB,EACnB,UAAU,EACV,MAAM,EAGP,MAAM,SAAS,CAAC;AA+BjB;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,cAgE7G;AAwCD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,mBAAmB,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAE,MAAM,GAAG,IAAW,cA0FnH"}
|
|
@@ -47,8 +47,17 @@ export function trackHtmlVideo(videoEl, handlers, vendor) {
|
|
|
47
47
|
handlers.onSeeking(seekingEvent);
|
|
48
48
|
};
|
|
49
49
|
videoEl.addEventListener('seeking', seekingHandler);
|
|
50
|
+
var seekedHandler = function () {
|
|
51
|
+
var seekedEvent = __assign(__assign({}, getVideoData(videoEl)), (vendor === 'mux' ? getMuxMetadata(videoEl) : {}));
|
|
52
|
+
handlers.onSeeked(seekedEvent);
|
|
53
|
+
};
|
|
54
|
+
videoEl.addEventListener('seeked', seekedHandler);
|
|
50
55
|
var timeupdateHandler = function () {
|
|
51
|
-
var
|
|
56
|
+
var media = videoEl;
|
|
57
|
+
var timeupdateEvent = {
|
|
58
|
+
position: videoEl.currentTime,
|
|
59
|
+
isSeeking: !!media.seeking,
|
|
60
|
+
};
|
|
52
61
|
handlers.onTimeUpdate(timeupdateEvent);
|
|
53
62
|
};
|
|
54
63
|
videoEl.addEventListener('timeupdate', timeupdateHandler);
|
|
@@ -57,9 +66,23 @@ export function trackHtmlVideo(videoEl, handlers, vendor) {
|
|
|
57
66
|
videoEl.removeEventListener('pause', pauseHandler);
|
|
58
67
|
videoEl.removeEventListener('ended', endedHandler);
|
|
59
68
|
videoEl.removeEventListener('seeking', seekingHandler);
|
|
69
|
+
videoEl.removeEventListener('seeked', seekedHandler);
|
|
60
70
|
videoEl.removeEventListener('timeupdate', timeupdateHandler);
|
|
61
71
|
};
|
|
62
72
|
}
|
|
73
|
+
function getTimeUpdateInfo(player) {
|
|
74
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
75
|
+
var currentTime;
|
|
76
|
+
return __generator(this, function (_a) {
|
|
77
|
+
switch (_a.label) {
|
|
78
|
+
case 0: return [4 /*yield*/, new Promise(function (resolve) { return player.getCurrentTime(resolve); })];
|
|
79
|
+
case 1:
|
|
80
|
+
currentTime = _a.sent();
|
|
81
|
+
return [2 /*return*/, { currentTime: currentTime }];
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
63
86
|
function getIframeMetadata(player, elem, vendor, stopReason) {
|
|
64
87
|
return __awaiter(this, void 0, void 0, function () {
|
|
65
88
|
var _a, duration, currentTime, vendorMetadata, url;
|
|
@@ -94,11 +117,11 @@ export function trackEmbeddedVideo(player, handlers, vendor) {
|
|
|
94
117
|
var onUnsubscribe = [];
|
|
95
118
|
var readyHandler = function () {
|
|
96
119
|
var elem = player.elem;
|
|
120
|
+
var isSeeking = false;
|
|
97
121
|
var playHandler = function () {
|
|
98
122
|
getIframeMetadata(player, elem, vendor)
|
|
99
123
|
.then(function (playerState) {
|
|
100
|
-
|
|
101
|
-
handlers.onPlay(startEvent);
|
|
124
|
+
handlers.onPlay(playerState);
|
|
102
125
|
})
|
|
103
126
|
.catch(function (error) {
|
|
104
127
|
handlers.onError("Error getting iframe metadata from 'play' handler: ".concat(error));
|
|
@@ -109,8 +132,7 @@ export function trackEmbeddedVideo(player, handlers, vendor) {
|
|
|
109
132
|
var pauseHandler = function () {
|
|
110
133
|
getIframeMetadata(player, elem, vendor, 'paused')
|
|
111
134
|
.then(function (playerState) {
|
|
112
|
-
|
|
113
|
-
handlers.onPause(pauseEvent);
|
|
135
|
+
handlers.onPause(playerState);
|
|
114
136
|
})
|
|
115
137
|
.catch(function (error) {
|
|
116
138
|
handlers.onError("Error getting iframe metadata from 'pause' handler: ".concat(error));
|
|
@@ -121,8 +143,7 @@ export function trackEmbeddedVideo(player, handlers, vendor) {
|
|
|
121
143
|
var endedHandler = function () {
|
|
122
144
|
getIframeMetadata(player, elem, vendor, 'ended')
|
|
123
145
|
.then(function (playerState) {
|
|
124
|
-
|
|
125
|
-
handlers.onEnded(endedEvent);
|
|
146
|
+
handlers.onEnded(playerState);
|
|
126
147
|
})
|
|
127
148
|
.catch(function (error) {
|
|
128
149
|
handlers.onError("Error getting iframe metadata from 'ended' handler: ".concat(error));
|
|
@@ -131,10 +152,10 @@ export function trackEmbeddedVideo(player, handlers, vendor) {
|
|
|
131
152
|
player.on('ended', endedHandler);
|
|
132
153
|
onUnsubscribe.push(function () { return player.off('ended', endedHandler); });
|
|
133
154
|
var seekingHandler = function () {
|
|
155
|
+
isSeeking = true;
|
|
134
156
|
getIframeMetadata(player, elem, vendor, 'seeking')
|
|
135
157
|
.then(function (playerState) {
|
|
136
|
-
|
|
137
|
-
handlers.onSeeking(seekingEvent);
|
|
158
|
+
handlers.onSeeking(playerState);
|
|
138
159
|
})
|
|
139
160
|
.catch(function (error) {
|
|
140
161
|
handlers.onError("Error getting iframe metadata from 'seeking' handler: ".concat(error));
|
|
@@ -142,10 +163,26 @@ export function trackEmbeddedVideo(player, handlers, vendor) {
|
|
|
142
163
|
};
|
|
143
164
|
player.on('seeking', seekingHandler);
|
|
144
165
|
onUnsubscribe.push(function () { return player.off('seeking', seekingHandler); });
|
|
145
|
-
var
|
|
166
|
+
var seekedHandler = function () {
|
|
167
|
+
isSeeking = false;
|
|
146
168
|
getIframeMetadata(player, elem, vendor)
|
|
147
169
|
.then(function (playerState) {
|
|
148
|
-
|
|
170
|
+
handlers.onSeeked(playerState);
|
|
171
|
+
})
|
|
172
|
+
.catch(function (error) {
|
|
173
|
+
handlers.onError("Error getting iframe metadata from 'seeked' handler: ".concat(error));
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
player.on('seeked', seekedHandler);
|
|
177
|
+
onUnsubscribe.push(function () { return player.off('seeked', seekedHandler); });
|
|
178
|
+
var timeupdateHandler = function () {
|
|
179
|
+
getTimeUpdateInfo(player)
|
|
180
|
+
.then(function (_a) {
|
|
181
|
+
var currentTime = _a.currentTime;
|
|
182
|
+
var timeupdateEvent = {
|
|
183
|
+
position: currentTime,
|
|
184
|
+
isSeeking: isSeeking,
|
|
185
|
+
};
|
|
149
186
|
handlers.onTimeUpdate(timeupdateEvent);
|
|
150
187
|
})
|
|
151
188
|
.catch(function (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"track-video.js","sourceRoot":"","sources":["../../../src/video-analytics/track-video.ts"],"names":[],"mappings":"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","sourcesContent":["import { VideoHandler, VideoEvent, EmbeddedVideoPlayer, MuxElement, Vendor, VideoStopReason } from './types';\n\nfunction calculatePercentCompleted(currentTime: number, duration: number) {\n let percentCompleted = 0;\n if (Number.isFinite(currentTime) && Number.isFinite(duration) && duration > 0) {\n const rawPercent = (currentTime / duration) * 100;\n percentCompleted = Math.min(100, Math.max(0, rawPercent));\n }\n return percentCompleted;\n}\n\nfunction getVideoData(videoEl: HTMLVideoElement | MuxElement, stopReason?: VideoStopReason) {\n const currentTime = videoEl.currentTime;\n const duration = videoEl.duration;\n return {\n duration,\n start_time: currentTime,\n last_position: currentTime,\n percent_completed: calculatePercentCompleted(currentTime, duration),\n ...(stopReason !== undefined ? { stop_reason: stopReason } : {}),\n };\n}\n\nfunction getMuxMetadata(videoEl: MuxElement) {\n return {\n mux_playback_id: videoEl.getAttribute('playback-id'),\n mux_video_id: videoEl.getAttribute('metadata-video-id'),\n mux_video_title: videoEl.getAttribute('metadata-video-title'),\n };\n}\n\n/**\n * Track a standard HTML video element.\n *\n * @param videoEl - The HTML video element to track.\n * @param handlers - The video handlers to call when on video lifecycle events.\n * @returns A function to untrack the video.\n */\nexport function trackHtmlVideo(videoEl: HTMLVideoElement | MuxElement, handlers: VideoHandler, vendor?: Vendor) {\n const playHandler = () => {\n const startEvent: VideoEvent = {\n ...getVideoData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onPlay(startEvent);\n };\n videoEl.addEventListener('play', playHandler);\n\n const pauseHandler = () => {\n const pauseEvent: VideoEvent = {\n ...getVideoData(videoEl, 'paused'),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onPause(pauseEvent);\n };\n videoEl.addEventListener('pause', pauseHandler);\n\n const endedHandler = () => {\n const endedEvent: VideoEvent = {\n ...getVideoData(videoEl, 'ended'),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onEnded(endedEvent);\n };\n videoEl.addEventListener('ended', endedHandler);\n\n const seekingHandler = () => {\n const seekingEvent: VideoEvent = {\n ...getVideoData(videoEl, 'seeking'),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onSeeking(seekingEvent);\n };\n videoEl.addEventListener('seeking', seekingHandler);\n\n const timeupdateHandler = () => {\n const timeupdateEvent: VideoEvent = {\n ...getVideoData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onTimeUpdate(timeupdateEvent);\n };\n videoEl.addEventListener('timeupdate', timeupdateHandler);\n\n return () => {\n videoEl.removeEventListener('play', playHandler);\n videoEl.removeEventListener('pause', pauseHandler);\n videoEl.removeEventListener('ended', endedHandler);\n videoEl.removeEventListener('seeking', seekingHandler);\n videoEl.removeEventListener('timeupdate', timeupdateHandler);\n };\n}\n\nasync function getIframeMetadata(\n player: EmbeddedVideoPlayer,\n elem: HTMLIFrameElement,\n vendor: Vendor | null,\n stopReason?: VideoStopReason,\n) {\n const [duration, currentTime] = await Promise.all([\n new Promise<number>((resolve) => player.getDuration(resolve)),\n new Promise<number>((resolve) => player.getCurrentTime(resolve)),\n ]);\n\n const vendorMetadata: Record<string, string | null | undefined> = {};\n if (vendor === 'mux') {\n let url;\n try {\n url = new URL(elem.getAttribute('src') as string);\n vendorMetadata.mux_video_title = url.searchParams.get('metadata-video-title');\n vendorMetadata.mux_video_id = url.searchParams.get('metadata-video-id');\n vendorMetadata.mux_playback_id = url.pathname.split('/').pop();\n } catch (error) {\n // invalid or no src url, skip the header metadata\n }\n }\n return {\n duration,\n start_time: currentTime,\n last_position: currentTime,\n percent_completed: calculatePercentCompleted(currentTime, duration),\n ...(stopReason !== undefined ? { stop_reason: stopReason } : {}),\n ...vendorMetadata,\n };\n}\n\nexport function trackEmbeddedVideo(player: EmbeddedVideoPlayer, handlers: VideoHandler, vendor: Vendor | null = null) {\n const onUnsubscribe: (() => void)[] = [];\n const readyHandler = () => {\n const { elem } = player;\n const playHandler = () => {\n getIframeMetadata(player, elem, vendor)\n .then((playerState) => {\n const startEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onPlay(startEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'play' handler: ${error as string}`);\n });\n };\n player.on('play', playHandler);\n onUnsubscribe.push(() => player.off('play', playHandler));\n\n const pauseHandler = () => {\n getIframeMetadata(player, elem, vendor, 'paused')\n .then((playerState) => {\n const pauseEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onPause(pauseEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'pause' handler: ${error as string}`);\n });\n };\n player.on('pause', pauseHandler);\n onUnsubscribe.push(() => player.off('pause', pauseHandler));\n\n const endedHandler = () => {\n getIframeMetadata(player, elem, vendor, 'ended')\n .then((playerState) => {\n const endedEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onEnded(endedEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'ended' handler: ${error as string}`);\n });\n };\n player.on('ended', endedHandler);\n onUnsubscribe.push(() => player.off('ended', endedHandler));\n\n const seekingHandler = () => {\n getIframeMetadata(player, elem, vendor, 'seeking')\n .then((playerState) => {\n const seekingEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onSeeking(seekingEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'seeking' handler: ${error as string}`);\n });\n };\n player.on('seeking', seekingHandler);\n onUnsubscribe.push(() => player.off('seeking', seekingHandler));\n\n const timeupdateHandler = () => {\n getIframeMetadata(player, elem, vendor)\n .then((playerState) => {\n const timeupdateEvent: VideoEvent = {\n ...playerState,\n };\n handlers.onTimeUpdate(timeupdateEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'timeupdate' handler: ${error as string}`);\n });\n };\n player.on('timeupdate', timeupdateHandler);\n onUnsubscribe.push(() => player.off('timeupdate', timeupdateHandler));\n };\n player.on('ready', readyHandler);\n\n return () => {\n player.off('ready', readyHandler);\n onUnsubscribe.forEach((unsubscribe) => unsubscribe());\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"track-video.js","sourceRoot":"","sources":["../../../src/video-analytics/track-video.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n VideoHandler,\n VideoEvent,\n EmbeddedVideoPlayer,\n MuxElement,\n Vendor,\n VideoStopReason,\n TimeUpdateEvent,\n} from './types';\n\nfunction calculatePercentCompleted(currentTime: number, duration: number) {\n let percentCompleted = 0;\n if (Number.isFinite(currentTime) && Number.isFinite(duration) && duration > 0) {\n const rawPercent = (currentTime / duration) * 100;\n percentCompleted = Math.min(100, Math.max(0, rawPercent));\n }\n return percentCompleted;\n}\n\nfunction getVideoData(videoEl: HTMLVideoElement | MuxElement, stopReason?: VideoStopReason) {\n const currentTime = videoEl.currentTime;\n const duration = videoEl.duration;\n return {\n duration,\n start_time: currentTime,\n last_position: currentTime,\n percent_completed: calculatePercentCompleted(currentTime, duration),\n ...(stopReason !== undefined ? { stop_reason: stopReason } : {}),\n };\n}\n\nfunction getMuxMetadata(videoEl: MuxElement) {\n return {\n mux_playback_id: videoEl.getAttribute('playback-id'),\n mux_video_id: videoEl.getAttribute('metadata-video-id'),\n mux_video_title: videoEl.getAttribute('metadata-video-title'),\n };\n}\n\n/**\n * Track a standard HTML video element.\n *\n * @param videoEl - The HTML video element to track.\n * @param handlers - The video handlers to call when on video lifecycle events.\n * @returns A function to untrack the video.\n */\nexport function trackHtmlVideo(videoEl: HTMLVideoElement | MuxElement, handlers: VideoHandler, vendor?: Vendor) {\n const playHandler = () => {\n const startEvent: VideoEvent = {\n ...getVideoData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onPlay(startEvent);\n };\n videoEl.addEventListener('play', playHandler);\n\n const pauseHandler = () => {\n const pauseEvent: VideoEvent = {\n ...getVideoData(videoEl, 'paused'),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onPause(pauseEvent);\n };\n videoEl.addEventListener('pause', pauseHandler);\n\n const endedHandler = () => {\n const endedEvent: VideoEvent = {\n ...getVideoData(videoEl, 'ended'),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onEnded(endedEvent);\n };\n videoEl.addEventListener('ended', endedHandler);\n\n const seekingHandler = () => {\n const seekingEvent: VideoEvent = {\n ...getVideoData(videoEl, 'seeking'),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onSeeking(seekingEvent);\n };\n videoEl.addEventListener('seeking', seekingHandler);\n\n const seekedHandler = () => {\n const seekedEvent: VideoEvent = {\n ...getVideoData(videoEl),\n ...(vendor === 'mux' ? getMuxMetadata(videoEl) : {}),\n };\n handlers.onSeeked(seekedEvent);\n };\n videoEl.addEventListener('seeked', seekedHandler);\n\n const timeupdateHandler = () => {\n const media = videoEl as HTMLVideoElement;\n const timeupdateEvent: TimeUpdateEvent = {\n position: videoEl.currentTime,\n isSeeking: !!media.seeking,\n };\n handlers.onTimeUpdate(timeupdateEvent);\n };\n videoEl.addEventListener('timeupdate', timeupdateHandler);\n\n return () => {\n videoEl.removeEventListener('play', playHandler);\n videoEl.removeEventListener('pause', pauseHandler);\n videoEl.removeEventListener('ended', endedHandler);\n videoEl.removeEventListener('seeking', seekingHandler);\n videoEl.removeEventListener('seeked', seekedHandler);\n videoEl.removeEventListener('timeupdate', timeupdateHandler);\n };\n}\n\nasync function getTimeUpdateInfo(player: EmbeddedVideoPlayer) {\n const currentTime = await new Promise<number>((resolve) => player.getCurrentTime(resolve));\n return { currentTime };\n}\n\nasync function getIframeMetadata(\n player: EmbeddedVideoPlayer,\n elem: HTMLIFrameElement,\n vendor: Vendor | null,\n stopReason?: VideoStopReason,\n) {\n const [duration, currentTime] = await Promise.all([\n new Promise<number>((resolve) => player.getDuration(resolve)),\n new Promise<number>((resolve) => player.getCurrentTime(resolve)),\n ]);\n\n const vendorMetadata: Record<string, string | null | undefined> = {};\n if (vendor === 'mux') {\n let url;\n try {\n url = new URL(elem.getAttribute('src') as string);\n vendorMetadata.mux_video_title = url.searchParams.get('metadata-video-title');\n vendorMetadata.mux_video_id = url.searchParams.get('metadata-video-id');\n vendorMetadata.mux_playback_id = url.pathname.split('/').pop();\n } catch (error) {\n // invalid or no src url, skip the header metadata\n }\n }\n return {\n duration,\n start_time: currentTime,\n last_position: currentTime,\n percent_completed: calculatePercentCompleted(currentTime, duration),\n ...(stopReason !== undefined ? { stop_reason: stopReason } : {}),\n ...vendorMetadata,\n };\n}\n\nexport function trackEmbeddedVideo(player: EmbeddedVideoPlayer, handlers: VideoHandler, vendor: Vendor | null = null) {\n const onUnsubscribe: (() => void)[] = [];\n const readyHandler = () => {\n const { elem } = player;\n let isSeeking = false;\n\n const playHandler = () => {\n getIframeMetadata(player, elem, vendor)\n .then((playerState) => {\n handlers.onPlay(playerState);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'play' handler: ${error as string}`);\n });\n };\n player.on('play', playHandler);\n onUnsubscribe.push(() => player.off('play', playHandler));\n\n const pauseHandler = () => {\n getIframeMetadata(player, elem, vendor, 'paused')\n .then((playerState) => {\n handlers.onPause(playerState);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'pause' handler: ${error as string}`);\n });\n };\n player.on('pause', pauseHandler);\n onUnsubscribe.push(() => player.off('pause', pauseHandler));\n\n const endedHandler = () => {\n getIframeMetadata(player, elem, vendor, 'ended')\n .then((playerState) => {\n handlers.onEnded(playerState);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'ended' handler: ${error as string}`);\n });\n };\n player.on('ended', endedHandler);\n onUnsubscribe.push(() => player.off('ended', endedHandler));\n\n const seekingHandler = () => {\n isSeeking = true;\n getIframeMetadata(player, elem, vendor, 'seeking')\n .then((playerState) => {\n handlers.onSeeking(playerState);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'seeking' handler: ${error as string}`);\n });\n };\n player.on('seeking', seekingHandler);\n onUnsubscribe.push(() => player.off('seeking', seekingHandler));\n\n const seekedHandler = () => {\n isSeeking = false;\n getIframeMetadata(player, elem, vendor)\n .then((playerState) => {\n handlers.onSeeked(playerState);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'seeked' handler: ${error as string}`);\n });\n };\n player.on('seeked', seekedHandler);\n onUnsubscribe.push(() => player.off('seeked', seekedHandler));\n\n const timeupdateHandler = () => {\n getTimeUpdateInfo(player)\n .then(({ currentTime }) => {\n const timeupdateEvent: TimeUpdateEvent = {\n position: currentTime,\n isSeeking: isSeeking,\n };\n handlers.onTimeUpdate(timeupdateEvent);\n })\n .catch((error) => {\n handlers.onError(`Error getting iframe metadata from 'timeupdate' handler: ${error as string}`);\n });\n };\n player.on('timeupdate', timeupdateHandler);\n onUnsubscribe.push(() => player.off('timeupdate', timeupdateHandler));\n };\n player.on('ready', readyHandler);\n\n return () => {\n player.off('ready', readyHandler);\n onUnsubscribe.forEach((unsubscribe) => unsubscribe());\n };\n}\n"]}
|
|
@@ -5,8 +5,9 @@ export type VideoHandler = {
|
|
|
5
5
|
onPause: (pauseEvent: VideoEvent) => void;
|
|
6
6
|
onEnded: (endedEvent: VideoEvent) => void;
|
|
7
7
|
onSeeking: (seekingEvent: VideoEvent) => void;
|
|
8
|
+
onSeeked: (seekedEvent: VideoEvent) => void;
|
|
8
9
|
onError: (error: string) => void;
|
|
9
|
-
onTimeUpdate: (timeUpdateEvent:
|
|
10
|
+
onTimeUpdate: (timeUpdateEvent: TimeUpdateEvent) => void;
|
|
10
11
|
};
|
|
11
12
|
export type VideoEvent = {
|
|
12
13
|
duration: number;
|
|
@@ -21,10 +22,14 @@ export type VideoEvent = {
|
|
|
21
22
|
mux_video_id?: string | undefined | null;
|
|
22
23
|
mux_video_title?: string | undefined | null;
|
|
23
24
|
mux_session_id?: string | undefined | null;
|
|
24
|
-
last_position
|
|
25
|
+
last_position: number | undefined | null;
|
|
25
26
|
percent_completed?: number;
|
|
26
27
|
stop_reason?: VideoStopReason;
|
|
27
28
|
};
|
|
29
|
+
export type TimeUpdateEvent = {
|
|
30
|
+
position: number;
|
|
31
|
+
isSeeking: boolean;
|
|
32
|
+
};
|
|
28
33
|
type EmbeddedVideoPlayer = {
|
|
29
34
|
getCurrentTime: (cb: (time: number) => void) => void;
|
|
30
35
|
getDuration: (cb: (duration: number) => void) => void;
|
|
@@ -33,6 +38,7 @@ type EmbeddedVideoPlayer = {
|
|
|
33
38
|
elem: HTMLIFrameElement;
|
|
34
39
|
};
|
|
35
40
|
type MuxElement = EventTarget & Element & {
|
|
41
|
+
seeking: boolean;
|
|
36
42
|
duration: number;
|
|
37
43
|
currentTime: number;
|
|
38
44
|
play?: () => Promise<unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/video-analytics/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC;AAE3B,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7D,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,SAAS,EAAE,CAAC,YAAY,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9C,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,YAAY,EAAE,CAAC,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/video-analytics/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,MAAM,GAAG,KAAK,CAAC;AAE3B,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7D,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,SAAS,EAAE,CAAC,YAAY,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9C,QAAQ,EAAE,CAAC,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;IAC5C,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,YAAY,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,IAAI,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACzC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5C,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAC3C,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;IACrD,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;IACtD,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAClD,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACnD,IAAI,EAAE,iBAAiB,CAAC;CACzB,CAAC;AAEF,KAAK,UAAU,GAAG,WAAW,GAC3B,OAAO,GAAG;IACR,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAEJ,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/video-analytics/types.ts"],"names":[],"mappings":"","sourcesContent":["export type Vendor = 'mux'; // | 'vimeo' | 'youtube' | 'other'\n\nexport type VideoStopReason = 'paused' | 'ended' | 'seeking';\n\nexport type VideoHandler = {\n onPlay: (startEvent: VideoEvent) => void;\n onPause: (pauseEvent: VideoEvent) => void;\n onEnded: (endedEvent: VideoEvent) => void;\n onSeeking: (seekingEvent: VideoEvent) => void;\n onError: (error: string) => void;\n onTimeUpdate: (timeUpdateEvent:
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/video-analytics/types.ts"],"names":[],"mappings":"","sourcesContent":["export type Vendor = 'mux'; // | 'vimeo' | 'youtube' | 'other'\n\nexport type VideoStopReason = 'paused' | 'ended' | 'seeking';\n\nexport type VideoHandler = {\n onPlay: (startEvent: VideoEvent) => void;\n onPause: (pauseEvent: VideoEvent) => void;\n onEnded: (endedEvent: VideoEvent) => void;\n onSeeking: (seekingEvent: VideoEvent) => void;\n onSeeked: (seekedEvent: VideoEvent) => void;\n onError: (error: string) => void;\n onTimeUpdate: (timeUpdateEvent: TimeUpdateEvent) => void;\n};\n\nexport type VideoEvent = {\n duration: number;\n start_time?: number;\n playback_id?: string | undefined;\n video_id?: string | undefined;\n video_title?: string | undefined;\n content_id?: string | undefined;\n content_type?: string | undefined;\n session_id?: string | undefined;\n mux_playback_id?: string | undefined | null;\n mux_video_id?: string | undefined | null;\n mux_video_title?: string | undefined | null;\n mux_session_id?: string | undefined | null;\n last_position: number | undefined | null;\n percent_completed?: number;\n stop_reason?: VideoStopReason;\n};\n\nexport type TimeUpdateEvent = {\n position: number;\n isSeeking: boolean;\n};\n\ntype EmbeddedVideoPlayer = {\n getCurrentTime: (cb: (time: number) => void) => void;\n getDuration: (cb: (duration: number) => void) => void;\n on: (event: string, callback: () => void) => void;\n off: (event: string, callback: () => void) => void;\n elem: HTMLIFrameElement;\n};\n\ntype MuxElement = EventTarget &\n Element & {\n seeking: boolean;\n duration: number;\n currentTime: number;\n play?: () => Promise<unknown>;\n pause?: () => void;\n };\n\nexport { MuxElement, EmbeddedVideoPlayer };\n"]}
|