@grainql/analytics-web 2.5.4 → 2.7.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/README.md +3 -1
- package/dist/activity.js +1 -1
- package/dist/attention-quality.d.ts +128 -0
- package/dist/attention-quality.d.ts.map +1 -0
- package/dist/attention-quality.js +246 -0
- package/dist/cjs/activity.js +1 -1
- package/dist/cjs/activity.js.map +1 -1
- package/dist/cjs/attention-quality.d.ts +128 -0
- package/dist/cjs/attention-quality.d.ts.map +1 -0
- package/dist/cjs/attention-quality.js +246 -0
- package/dist/cjs/attention-quality.js.map +1 -0
- package/dist/cjs/consent.js +4 -4
- package/dist/cjs/consent.js.map +1 -1
- package/dist/cjs/heartbeat.d.ts.map +1 -1
- package/dist/cjs/heartbeat.js +0 -6
- package/dist/cjs/heartbeat.js.map +1 -1
- package/dist/cjs/heatmap-tracking.d.ts +93 -0
- package/dist/cjs/heatmap-tracking.d.ts.map +1 -0
- package/dist/cjs/heatmap-tracking.js +499 -0
- package/dist/cjs/heatmap-tracking.js.map +1 -0
- package/dist/cjs/index.d.ts +11 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interaction-tracking.d.ts.map +1 -1
- package/dist/cjs/interaction-tracking.js +9 -18
- package/dist/cjs/interaction-tracking.js.map +1 -1
- package/dist/cjs/page-tracking.d.ts.map +1 -1
- package/dist/cjs/page-tracking.js +0 -9
- package/dist/cjs/page-tracking.js.map +1 -1
- package/dist/cjs/section-tracking.d.ts +3 -0
- package/dist/cjs/section-tracking.d.ts.map +1 -1
- package/dist/cjs/section-tracking.js +30 -7
- package/dist/cjs/section-tracking.js.map +1 -1
- package/dist/cjs/types/auto-tracking.d.ts +3 -0
- package/dist/cjs/types/auto-tracking.d.ts.map +1 -1
- package/dist/cjs/types/heatmap-tracking.d.ts +44 -0
- package/dist/cjs/types/heatmap-tracking.d.ts.map +1 -0
- package/dist/cjs/types/heatmap-tracking.js +6 -0
- package/dist/cjs/types/heatmap-tracking.js.map +1 -0
- package/dist/consent.js +4 -4
- package/dist/esm/activity.js +1 -1
- package/dist/esm/activity.js.map +1 -1
- package/dist/esm/attention-quality.d.ts +128 -0
- package/dist/esm/attention-quality.d.ts.map +1 -0
- package/dist/esm/attention-quality.js +242 -0
- package/dist/esm/attention-quality.js.map +1 -0
- package/dist/esm/consent.js +4 -4
- package/dist/esm/consent.js.map +1 -1
- package/dist/esm/heartbeat.d.ts.map +1 -1
- package/dist/esm/heartbeat.js +0 -6
- package/dist/esm/heartbeat.js.map +1 -1
- package/dist/esm/heatmap-tracking.d.ts +93 -0
- package/dist/esm/heatmap-tracking.d.ts.map +1 -0
- package/dist/esm/heatmap-tracking.js +495 -0
- package/dist/esm/heatmap-tracking.js.map +1 -0
- package/dist/esm/index.d.ts +11 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interaction-tracking.d.ts.map +1 -1
- package/dist/esm/interaction-tracking.js +9 -18
- package/dist/esm/interaction-tracking.js.map +1 -1
- package/dist/esm/page-tracking.d.ts.map +1 -1
- package/dist/esm/page-tracking.js +0 -9
- package/dist/esm/page-tracking.js.map +1 -1
- package/dist/esm/section-tracking.d.ts +3 -0
- package/dist/esm/section-tracking.d.ts.map +1 -1
- package/dist/esm/section-tracking.js +30 -7
- package/dist/esm/section-tracking.js.map +1 -1
- package/dist/esm/types/auto-tracking.d.ts +3 -0
- package/dist/esm/types/auto-tracking.d.ts.map +1 -1
- package/dist/esm/types/heatmap-tracking.d.ts +44 -0
- package/dist/esm/types/heatmap-tracking.d.ts.map +1 -0
- package/dist/esm/types/heatmap-tracking.js +5 -0
- package/dist/esm/types/heatmap-tracking.js.map +1 -0
- package/dist/heartbeat.d.ts.map +1 -1
- package/dist/heartbeat.js +0 -6
- package/dist/heatmap-tracking.d.ts +93 -0
- package/dist/heatmap-tracking.d.ts.map +1 -0
- package/dist/heatmap-tracking.js +499 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.global.dev.js +801 -80
- package/dist/index.global.dev.js.map +4 -4
- package/dist/index.global.js +2 -2
- package/dist/index.global.js.map +4 -4
- package/dist/index.js +70 -38
- package/dist/index.mjs +70 -38
- package/dist/interaction-tracking.d.ts.map +1 -1
- package/dist/interaction-tracking.js +9 -18
- package/dist/page-tracking.d.ts.map +1 -1
- package/dist/page-tracking.js +0 -9
- package/dist/section-tracking.d.ts +3 -0
- package/dist/section-tracking.d.ts.map +1 -1
- package/dist/section-tracking.js +30 -7
- package/dist/types/auto-tracking.d.ts +3 -0
- package/dist/types/auto-tracking.d.ts.map +1 -1
- package/dist/types/heatmap-tracking.d.ts +44 -0
- package/dist/types/heatmap-tracking.d.ts.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -93,7 +93,9 @@ For comprehensive guides, API reference, and examples, visit our documentation:
|
|
|
93
93
|
|
|
94
94
|
### Key Topics
|
|
95
95
|
|
|
96
|
-
- **[Quick Start
|
|
96
|
+
- **[Quick Start Guides](https://docs.grainql.com/quickstart)** - Choose your platform and get started in 5 minutes
|
|
97
|
+
- [React](https://docs.grainql.com/quickstart/react) | [Next.js](https://docs.grainql.com/quickstart/nextjs) | [Vanilla JS](https://docs.grainql.com/quickstart/vanilla-js) | [CDN](https://docs.grainql.com/quickstart/cdn) | [Node.js](https://docs.grainql.com/quickstart/nodejs)
|
|
98
|
+
- **[No-Code Integrations](https://docs.grainql.com/integrations/gtm)** - GTM, Shopify, WordPress
|
|
97
99
|
- **[Event Tracking](https://docs.grainql.com/core/event-tracking)** - Track user actions
|
|
98
100
|
- **[Remote Configuration](https://docs.grainql.com/core/remote-config)** - Dynamic app control
|
|
99
101
|
- **[React Hooks](https://docs.grainql.com/react/overview)** - React integration
|
package/dist/activity.js
CHANGED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attention Quality Manager for Grain Analytics
|
|
3
|
+
* Enforces policies to ensure tracked data represents genuine user attention
|
|
4
|
+
*
|
|
5
|
+
* Policies:
|
|
6
|
+
* 1. Page Visibility: Stop tracking when tab is hidden/backgrounded
|
|
7
|
+
* 2. User Activity: Stop tracking when user is idle (no mouse/keyboard/touch)
|
|
8
|
+
* 3. Section Duration Cap: Max attention per section before requiring transition
|
|
9
|
+
* 4. Scroll Distance: Minimum scroll distance to count as meaningful engagement
|
|
10
|
+
*
|
|
11
|
+
* See: ATTENTION_QUALITY_POLICY.md for detailed policy documentation
|
|
12
|
+
*/
|
|
13
|
+
import type { ActivityDetector } from './activity';
|
|
14
|
+
export interface AttentionQualityOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Maximum continuous attention duration per section (ms)
|
|
17
|
+
* Default: 9000 (9 seconds)
|
|
18
|
+
*/
|
|
19
|
+
maxSectionDuration?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Minimum scroll distance to reset attention timer (px)
|
|
22
|
+
* Default: 100
|
|
23
|
+
*/
|
|
24
|
+
minScrollDistance?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Idle threshold - stop tracking after this period of inactivity (ms)
|
|
27
|
+
* Default: 30000 (30 seconds)
|
|
28
|
+
*/
|
|
29
|
+
idleThreshold?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Enable debug logging
|
|
32
|
+
*/
|
|
33
|
+
debug?: boolean;
|
|
34
|
+
}
|
|
35
|
+
interface SectionAttentionState {
|
|
36
|
+
sectionName: string;
|
|
37
|
+
currentDuration: number;
|
|
38
|
+
lastScrollPosition: number;
|
|
39
|
+
lastResetTime: number;
|
|
40
|
+
}
|
|
41
|
+
export declare class AttentionQualityManager {
|
|
42
|
+
private options;
|
|
43
|
+
private activityDetector;
|
|
44
|
+
private isDestroyed;
|
|
45
|
+
private isPageVisible;
|
|
46
|
+
private visibilityChangeHandler;
|
|
47
|
+
private sectionStates;
|
|
48
|
+
private lastFilterReason;
|
|
49
|
+
constructor(activityDetector: ActivityDetector, options?: AttentionQualityOptions);
|
|
50
|
+
/**
|
|
51
|
+
* Setup page visibility tracking
|
|
52
|
+
*/
|
|
53
|
+
private setupPageVisibilityTracking;
|
|
54
|
+
/**
|
|
55
|
+
* Check if tracking should be allowed (global check)
|
|
56
|
+
* Returns true if tracking is allowed, false if it should be paused
|
|
57
|
+
*/
|
|
58
|
+
shouldTrack(): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Check if section view tracking should be allowed for a specific section
|
|
61
|
+
* @param sectionName - Section identifier
|
|
62
|
+
* @param currentScrollY - Current scroll position
|
|
63
|
+
* @returns Object with shouldTrack boolean and optional reason
|
|
64
|
+
*/
|
|
65
|
+
shouldTrackSection(sectionName: string, currentScrollY: number): {
|
|
66
|
+
shouldTrack: boolean;
|
|
67
|
+
reason?: string;
|
|
68
|
+
resetAttention?: boolean;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Update section duration (call this when tracking a section view event)
|
|
72
|
+
* @param sectionName - Section identifier
|
|
73
|
+
* @param durationMs - Duration to add to current attention block
|
|
74
|
+
*/
|
|
75
|
+
updateSectionDuration(sectionName: string, durationMs: number): void;
|
|
76
|
+
/**
|
|
77
|
+
* Reset attention for a specific section (call when user navigates to different section)
|
|
78
|
+
* @param sectionName - Section identifier
|
|
79
|
+
*/
|
|
80
|
+
resetSection(sectionName: string): void;
|
|
81
|
+
/**
|
|
82
|
+
* Reset all section attention states
|
|
83
|
+
*/
|
|
84
|
+
resetAllSections(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Get current attention state for a section (for debugging/monitoring)
|
|
87
|
+
*/
|
|
88
|
+
getSectionState(sectionName: string): SectionAttentionState | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* Get reason why last tracking attempt was filtered
|
|
91
|
+
*/
|
|
92
|
+
getLastFilterReason(): string | null;
|
|
93
|
+
/**
|
|
94
|
+
* Check if scroll tracking should be allowed
|
|
95
|
+
* Similar to shouldTrack() but also checks scroll-specific conditions
|
|
96
|
+
*/
|
|
97
|
+
shouldTrackScroll(previousScrollY: number, currentScrollY: number): {
|
|
98
|
+
shouldTrack: boolean;
|
|
99
|
+
reason?: string;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Get all active policies as object (for monitoring/debugging)
|
|
103
|
+
*/
|
|
104
|
+
getPolicies(): {
|
|
105
|
+
maxSectionDuration: number;
|
|
106
|
+
minScrollDistance: number;
|
|
107
|
+
idleThreshold: number;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Get current tracking state (for monitoring/debugging)
|
|
111
|
+
*/
|
|
112
|
+
getTrackingState(): {
|
|
113
|
+
isPageVisible: boolean;
|
|
114
|
+
isUserActive: boolean;
|
|
115
|
+
timeSinceLastActivity: number;
|
|
116
|
+
activeSections: number;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Log debug messages
|
|
120
|
+
*/
|
|
121
|
+
private log;
|
|
122
|
+
/**
|
|
123
|
+
* Destroy and cleanup
|
|
124
|
+
*/
|
|
125
|
+
destroy(): void;
|
|
126
|
+
}
|
|
127
|
+
export {};
|
|
128
|
+
//# sourceMappingURL=attention-quality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attention-quality.d.ts","sourceRoot":"","sources":["../src/attention-quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,UAAU,qBAAqB;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;CACvB;AAQD,qBAAa,uBAAuB;IAClC,OAAO,CAAC,OAAO,CAAwE;IACvF,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,uBAAuB,CAA6B;IAG5D,OAAO,CAAC,aAAa,CAA4C;IAGjE,OAAO,CAAC,gBAAgB,CAAuB;gBAEnC,gBAAgB,EAAE,gBAAgB,EAAE,OAAO,GAAE,uBAA4B;IAWrF;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAqBnC;;;OAGG;IACH,WAAW,IAAI,OAAO;IAiBtB;;;;;OAKG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG;QAC/D,WAAW,EAAE,OAAO,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B;IAkDD;;;;OAIG;IACH,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAWpE;;;OAGG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IASvC;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAQxB;;OAEG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAIvE;;OAEG;IACH,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC;;;OAGG;IACH,iBAAiB,CAAC,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG;QAClE,WAAW,EAAE,OAAO,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IAuBD;;OAEG;IACH,WAAW,IAAI;QACb,kBAAkB,EAAE,MAAM,CAAC;QAC3B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;KACvB;IAQD;;OAEG;IACH,gBAAgB,IAAI;QAClB,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,cAAc,EAAE,MAAM,CAAC;KACxB;IASD;;OAEG;IACH,OAAO,CAAC,GAAG;IAMX;;OAEG;IACH,OAAO,IAAI,IAAI;CAchB"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Attention Quality Manager for Grain Analytics
|
|
4
|
+
* Enforces policies to ensure tracked data represents genuine user attention
|
|
5
|
+
*
|
|
6
|
+
* Policies:
|
|
7
|
+
* 1. Page Visibility: Stop tracking when tab is hidden/backgrounded
|
|
8
|
+
* 2. User Activity: Stop tracking when user is idle (no mouse/keyboard/touch)
|
|
9
|
+
* 3. Section Duration Cap: Max attention per section before requiring transition
|
|
10
|
+
* 4. Scroll Distance: Minimum scroll distance to count as meaningful engagement
|
|
11
|
+
*
|
|
12
|
+
* See: ATTENTION_QUALITY_POLICY.md for detailed policy documentation
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.AttentionQualityManager = void 0;
|
|
16
|
+
const DEFAULT_OPTIONS = {
|
|
17
|
+
maxSectionDuration: 9000, // 9 seconds
|
|
18
|
+
minScrollDistance: 100, // 100 pixels
|
|
19
|
+
idleThreshold: 30000, // 30 seconds
|
|
20
|
+
};
|
|
21
|
+
class AttentionQualityManager {
|
|
22
|
+
constructor(activityDetector, options = {}) {
|
|
23
|
+
this.isDestroyed = false;
|
|
24
|
+
// Page visibility tracking
|
|
25
|
+
this.isPageVisible = true;
|
|
26
|
+
this.visibilityChangeHandler = null;
|
|
27
|
+
// Section attention state
|
|
28
|
+
this.sectionStates = new Map();
|
|
29
|
+
// Policies applied reasons (for debugging/traceability)
|
|
30
|
+
this.lastFilterReason = null;
|
|
31
|
+
this.activityDetector = activityDetector;
|
|
32
|
+
this.options = {
|
|
33
|
+
...DEFAULT_OPTIONS,
|
|
34
|
+
...options,
|
|
35
|
+
debug: options.debug ?? false,
|
|
36
|
+
};
|
|
37
|
+
this.setupPageVisibilityTracking();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Setup page visibility tracking
|
|
41
|
+
*/
|
|
42
|
+
setupPageVisibilityTracking() {
|
|
43
|
+
if (typeof document === 'undefined')
|
|
44
|
+
return;
|
|
45
|
+
this.isPageVisible = document.visibilityState === 'visible';
|
|
46
|
+
this.visibilityChangeHandler = () => {
|
|
47
|
+
const wasVisible = this.isPageVisible;
|
|
48
|
+
this.isPageVisible = document.visibilityState === 'visible';
|
|
49
|
+
if (!this.isPageVisible && wasVisible) {
|
|
50
|
+
this.log('Page hidden - tracking paused');
|
|
51
|
+
}
|
|
52
|
+
else if (this.isPageVisible && !wasVisible) {
|
|
53
|
+
this.log('Page visible - tracking resumed');
|
|
54
|
+
// Reset all section states when page becomes visible again
|
|
55
|
+
this.resetAllSections();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
document.addEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Check if tracking should be allowed (global check)
|
|
62
|
+
* Returns true if tracking is allowed, false if it should be paused
|
|
63
|
+
*/
|
|
64
|
+
shouldTrack() {
|
|
65
|
+
// Policy 1: Page Visibility
|
|
66
|
+
if (!this.isPageVisible) {
|
|
67
|
+
this.lastFilterReason = 'page_hidden';
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
// Policy 2: User Activity
|
|
71
|
+
if (!this.activityDetector.isActive(this.options.idleThreshold)) {
|
|
72
|
+
this.lastFilterReason = 'user_idle';
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
this.lastFilterReason = null;
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if section view tracking should be allowed for a specific section
|
|
80
|
+
* @param sectionName - Section identifier
|
|
81
|
+
* @param currentScrollY - Current scroll position
|
|
82
|
+
* @returns Object with shouldTrack boolean and optional reason
|
|
83
|
+
*/
|
|
84
|
+
shouldTrackSection(sectionName, currentScrollY) {
|
|
85
|
+
// First check global tracking state
|
|
86
|
+
if (!this.shouldTrack()) {
|
|
87
|
+
return {
|
|
88
|
+
shouldTrack: false,
|
|
89
|
+
reason: this.lastFilterReason || 'global_policy',
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Get or create section state
|
|
93
|
+
let state = this.sectionStates.get(sectionName);
|
|
94
|
+
if (!state) {
|
|
95
|
+
state = {
|
|
96
|
+
sectionName,
|
|
97
|
+
currentDuration: 0,
|
|
98
|
+
lastScrollPosition: currentScrollY,
|
|
99
|
+
lastResetTime: Date.now(),
|
|
100
|
+
};
|
|
101
|
+
this.sectionStates.set(sectionName, state);
|
|
102
|
+
}
|
|
103
|
+
// Policy 4: Scroll Distance - Check if user has scrolled enough to reset attention
|
|
104
|
+
const scrollDistance = Math.abs(currentScrollY - state.lastScrollPosition);
|
|
105
|
+
const hasScrolledEnough = scrollDistance >= this.options.minScrollDistance;
|
|
106
|
+
if (hasScrolledEnough) {
|
|
107
|
+
// Reset attention timer due to meaningful scroll
|
|
108
|
+
this.log(`Section "${sectionName}": Attention reset due to ${Math.round(scrollDistance)}px scroll`);
|
|
109
|
+
state.currentDuration = 0;
|
|
110
|
+
state.lastScrollPosition = currentScrollY;
|
|
111
|
+
state.lastResetTime = Date.now();
|
|
112
|
+
return {
|
|
113
|
+
shouldTrack: true,
|
|
114
|
+
resetAttention: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// Policy 3: Section Duration Cap
|
|
118
|
+
if (state.currentDuration >= this.options.maxSectionDuration) {
|
|
119
|
+
return {
|
|
120
|
+
shouldTrack: false,
|
|
121
|
+
reason: 'max_duration_reached',
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
shouldTrack: true,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Update section duration (call this when tracking a section view event)
|
|
130
|
+
* @param sectionName - Section identifier
|
|
131
|
+
* @param durationMs - Duration to add to current attention block
|
|
132
|
+
*/
|
|
133
|
+
updateSectionDuration(sectionName, durationMs) {
|
|
134
|
+
const state = this.sectionStates.get(sectionName);
|
|
135
|
+
if (state) {
|
|
136
|
+
state.currentDuration += durationMs;
|
|
137
|
+
if (state.currentDuration >= this.options.maxSectionDuration) {
|
|
138
|
+
this.log(`Section "${sectionName}": Max duration cap reached (${state.currentDuration}ms)`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Reset attention for a specific section (call when user navigates to different section)
|
|
144
|
+
* @param sectionName - Section identifier
|
|
145
|
+
*/
|
|
146
|
+
resetSection(sectionName) {
|
|
147
|
+
const state = this.sectionStates.get(sectionName);
|
|
148
|
+
if (state) {
|
|
149
|
+
this.log(`Section "${sectionName}": Attention reset (section exit)`);
|
|
150
|
+
state.currentDuration = 0;
|
|
151
|
+
state.lastResetTime = Date.now();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Reset all section attention states
|
|
156
|
+
*/
|
|
157
|
+
resetAllSections() {
|
|
158
|
+
this.log('Resetting all section attention states');
|
|
159
|
+
for (const state of this.sectionStates.values()) {
|
|
160
|
+
state.currentDuration = 0;
|
|
161
|
+
state.lastResetTime = Date.now();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get current attention state for a section (for debugging/monitoring)
|
|
166
|
+
*/
|
|
167
|
+
getSectionState(sectionName) {
|
|
168
|
+
return this.sectionStates.get(sectionName);
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Get reason why last tracking attempt was filtered
|
|
172
|
+
*/
|
|
173
|
+
getLastFilterReason() {
|
|
174
|
+
return this.lastFilterReason;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Check if scroll tracking should be allowed
|
|
178
|
+
* Similar to shouldTrack() but also checks scroll-specific conditions
|
|
179
|
+
*/
|
|
180
|
+
shouldTrackScroll(previousScrollY, currentScrollY) {
|
|
181
|
+
// First check global tracking state
|
|
182
|
+
if (!this.shouldTrack()) {
|
|
183
|
+
return {
|
|
184
|
+
shouldTrack: false,
|
|
185
|
+
reason: this.lastFilterReason || 'global_policy',
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
// Check if scroll is meaningful
|
|
189
|
+
const scrollDistance = Math.abs(currentScrollY - previousScrollY);
|
|
190
|
+
if (scrollDistance < 10) { // Minimum 10px to count as scroll
|
|
191
|
+
return {
|
|
192
|
+
shouldTrack: false,
|
|
193
|
+
reason: 'scroll_too_small',
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
shouldTrack: true,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get all active policies as object (for monitoring/debugging)
|
|
202
|
+
*/
|
|
203
|
+
getPolicies() {
|
|
204
|
+
return {
|
|
205
|
+
maxSectionDuration: this.options.maxSectionDuration,
|
|
206
|
+
minScrollDistance: this.options.minScrollDistance,
|
|
207
|
+
idleThreshold: this.options.idleThreshold,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get current tracking state (for monitoring/debugging)
|
|
212
|
+
*/
|
|
213
|
+
getTrackingState() {
|
|
214
|
+
return {
|
|
215
|
+
isPageVisible: this.isPageVisible,
|
|
216
|
+
isUserActive: this.activityDetector.isActive(this.options.idleThreshold),
|
|
217
|
+
timeSinceLastActivity: this.activityDetector.getTimeSinceLastActivity(),
|
|
218
|
+
activeSections: this.sectionStates.size,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Log debug messages
|
|
223
|
+
*/
|
|
224
|
+
log(...args) {
|
|
225
|
+
if (this.options.debug) {
|
|
226
|
+
console.log('[AttentionQuality]', ...args);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Destroy and cleanup
|
|
231
|
+
*/
|
|
232
|
+
destroy() {
|
|
233
|
+
if (this.isDestroyed)
|
|
234
|
+
return;
|
|
235
|
+
this.isDestroyed = true;
|
|
236
|
+
// Remove visibility change listener
|
|
237
|
+
if (this.visibilityChangeHandler && typeof document !== 'undefined') {
|
|
238
|
+
document.removeEventListener('visibilitychange', this.visibilityChangeHandler);
|
|
239
|
+
this.visibilityChangeHandler = null;
|
|
240
|
+
}
|
|
241
|
+
// Clear section states
|
|
242
|
+
this.sectionStates.clear();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
exports.AttentionQualityManager = AttentionQualityManager;
|
|
246
|
+
//# sourceMappingURL=attention-quality.js.map
|
package/dist/cjs/activity.js
CHANGED
package/dist/cjs/activity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../../src/activity.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../../src/activity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attention Quality Manager for Grain Analytics
|
|
3
|
+
* Enforces policies to ensure tracked data represents genuine user attention
|
|
4
|
+
*
|
|
5
|
+
* Policies:
|
|
6
|
+
* 1. Page Visibility: Stop tracking when tab is hidden/backgrounded
|
|
7
|
+
* 2. User Activity: Stop tracking when user is idle (no mouse/keyboard/touch)
|
|
8
|
+
* 3. Section Duration Cap: Max attention per section before requiring transition
|
|
9
|
+
* 4. Scroll Distance: Minimum scroll distance to count as meaningful engagement
|
|
10
|
+
*
|
|
11
|
+
* See: ATTENTION_QUALITY_POLICY.md for detailed policy documentation
|
|
12
|
+
*/
|
|
13
|
+
import type { ActivityDetector } from './activity';
|
|
14
|
+
export interface AttentionQualityOptions {
|
|
15
|
+
/**
|
|
16
|
+
* Maximum continuous attention duration per section (ms)
|
|
17
|
+
* Default: 9000 (9 seconds)
|
|
18
|
+
*/
|
|
19
|
+
maxSectionDuration?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Minimum scroll distance to reset attention timer (px)
|
|
22
|
+
* Default: 100
|
|
23
|
+
*/
|
|
24
|
+
minScrollDistance?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Idle threshold - stop tracking after this period of inactivity (ms)
|
|
27
|
+
* Default: 30000 (30 seconds)
|
|
28
|
+
*/
|
|
29
|
+
idleThreshold?: number;
|
|
30
|
+
/**
|
|
31
|
+
* Enable debug logging
|
|
32
|
+
*/
|
|
33
|
+
debug?: boolean;
|
|
34
|
+
}
|
|
35
|
+
interface SectionAttentionState {
|
|
36
|
+
sectionName: string;
|
|
37
|
+
currentDuration: number;
|
|
38
|
+
lastScrollPosition: number;
|
|
39
|
+
lastResetTime: number;
|
|
40
|
+
}
|
|
41
|
+
export declare class AttentionQualityManager {
|
|
42
|
+
private options;
|
|
43
|
+
private activityDetector;
|
|
44
|
+
private isDestroyed;
|
|
45
|
+
private isPageVisible;
|
|
46
|
+
private visibilityChangeHandler;
|
|
47
|
+
private sectionStates;
|
|
48
|
+
private lastFilterReason;
|
|
49
|
+
constructor(activityDetector: ActivityDetector, options?: AttentionQualityOptions);
|
|
50
|
+
/**
|
|
51
|
+
* Setup page visibility tracking
|
|
52
|
+
*/
|
|
53
|
+
private setupPageVisibilityTracking;
|
|
54
|
+
/**
|
|
55
|
+
* Check if tracking should be allowed (global check)
|
|
56
|
+
* Returns true if tracking is allowed, false if it should be paused
|
|
57
|
+
*/
|
|
58
|
+
shouldTrack(): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Check if section view tracking should be allowed for a specific section
|
|
61
|
+
* @param sectionName - Section identifier
|
|
62
|
+
* @param currentScrollY - Current scroll position
|
|
63
|
+
* @returns Object with shouldTrack boolean and optional reason
|
|
64
|
+
*/
|
|
65
|
+
shouldTrackSection(sectionName: string, currentScrollY: number): {
|
|
66
|
+
shouldTrack: boolean;
|
|
67
|
+
reason?: string;
|
|
68
|
+
resetAttention?: boolean;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Update section duration (call this when tracking a section view event)
|
|
72
|
+
* @param sectionName - Section identifier
|
|
73
|
+
* @param durationMs - Duration to add to current attention block
|
|
74
|
+
*/
|
|
75
|
+
updateSectionDuration(sectionName: string, durationMs: number): void;
|
|
76
|
+
/**
|
|
77
|
+
* Reset attention for a specific section (call when user navigates to different section)
|
|
78
|
+
* @param sectionName - Section identifier
|
|
79
|
+
*/
|
|
80
|
+
resetSection(sectionName: string): void;
|
|
81
|
+
/**
|
|
82
|
+
* Reset all section attention states
|
|
83
|
+
*/
|
|
84
|
+
resetAllSections(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Get current attention state for a section (for debugging/monitoring)
|
|
87
|
+
*/
|
|
88
|
+
getSectionState(sectionName: string): SectionAttentionState | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* Get reason why last tracking attempt was filtered
|
|
91
|
+
*/
|
|
92
|
+
getLastFilterReason(): string | null;
|
|
93
|
+
/**
|
|
94
|
+
* Check if scroll tracking should be allowed
|
|
95
|
+
* Similar to shouldTrack() but also checks scroll-specific conditions
|
|
96
|
+
*/
|
|
97
|
+
shouldTrackScroll(previousScrollY: number, currentScrollY: number): {
|
|
98
|
+
shouldTrack: boolean;
|
|
99
|
+
reason?: string;
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Get all active policies as object (for monitoring/debugging)
|
|
103
|
+
*/
|
|
104
|
+
getPolicies(): {
|
|
105
|
+
maxSectionDuration: number;
|
|
106
|
+
minScrollDistance: number;
|
|
107
|
+
idleThreshold: number;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Get current tracking state (for monitoring/debugging)
|
|
111
|
+
*/
|
|
112
|
+
getTrackingState(): {
|
|
113
|
+
isPageVisible: boolean;
|
|
114
|
+
isUserActive: boolean;
|
|
115
|
+
timeSinceLastActivity: number;
|
|
116
|
+
activeSections: number;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Log debug messages
|
|
120
|
+
*/
|
|
121
|
+
private log;
|
|
122
|
+
/**
|
|
123
|
+
* Destroy and cleanup
|
|
124
|
+
*/
|
|
125
|
+
destroy(): void;
|
|
126
|
+
}
|
|
127
|
+
export {};
|
|
128
|
+
//# sourceMappingURL=attention-quality.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attention-quality.d.ts","sourceRoot":"","sources":["../../src/attention-quality.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,WAAW,uBAAuB;IACtC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,UAAU,qBAAqB;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;CACvB;AAQD,qBAAa,uBAAuB;IAClC,OAAO,CAAC,OAAO,CAAwE;IACvF,OAAO,CAAC,gBAAgB,CAAmB;IAC3C,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,uBAAuB,CAA6B;IAG5D,OAAO,CAAC,aAAa,CAA4C;IAGjE,OAAO,CAAC,gBAAgB,CAAuB;gBAEnC,gBAAgB,EAAE,gBAAgB,EAAE,OAAO,GAAE,uBAA4B;IAWrF;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAqBnC;;;OAGG;IACH,WAAW,IAAI,OAAO;IAiBtB;;;;;OAKG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG;QAC/D,WAAW,EAAE,OAAO,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B;IAkDD;;;;OAIG;IACH,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAWpE;;;OAGG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IASvC;;OAEG;IACH,gBAAgB,IAAI,IAAI;IAQxB;;OAEG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS;IAIvE;;OAEG;IACH,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC;;;OAGG;IACH,iBAAiB,CAAC,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG;QAClE,WAAW,EAAE,OAAO,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB;IAuBD;;OAEG;IACH,WAAW,IAAI;QACb,kBAAkB,EAAE,MAAM,CAAC;QAC3B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;KACvB;IAQD;;OAEG;IACH,gBAAgB,IAAI;QAClB,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,cAAc,EAAE,MAAM,CAAC;KACxB;IASD;;OAEG;IACH,OAAO,CAAC,GAAG;IAMX;;OAEG;IACH,OAAO,IAAI,IAAI;CAchB"}
|