Skip to content

Data Schema

WriteTrack captures multiple types of events during typing sessions. This page documents the complete data schema.

Schema Version: v2.1.0

The primary event type, capturing individual key presses and releases.

interface KeystrokeEvent {
key: string; // Character or key name
code: string; // Physical key code
type: 'keydown' | 'keyup';
timestamp: number; // High-precision timestamp (ms)
dwellTime?: number; // Key hold duration (keyup only)
flightTime?: number; // Time since last key (keydown only)
isCorrection?: boolean; // True for Backspace, Delete, ArrowLeft, ArrowRight
windowFocused: boolean; // Window focus state
timeSinceLastMouse: number; // ms since last mouse activity
isTrusted?: boolean; // true if user-generated, false if scripted
inputSource?: InputSource; // Input source classification, set by editor integrations or beforeinput fallback
}

Dwell time: How long a key is held down (keydown to keyup).

  • Only present on keyup events
  • Typical human range: 50-200ms

Flight time: Time between releasing the previous key and pressing this one.

  • Only present on keydown events
  • Typical human range: 50-500ms

Captures copy, paste, and cut operations.

interface ClipboardEvent {
type: 'copy' | 'paste' | 'cut';
timestamp: number;
position: number; // Cursor position
length: number; // Length of content
shortcut: string; // e.g., 'Ctrl+V', 'Cmd+V'
content?: string; // Actual content (paste only)
beforeText?: string; // Text state before operation
afterText?: string; // Text state after operation
replacedText?: string; // Text that was replaced
replacedRange?: {
start: number;
end: number;
};
isTrusted?: boolean; // true if user-generated, false if scripted
inputSource?: InputSource; // Input source classification, set by editor integrations or beforeinput fallback
}
{
type: 'paste',
timestamp: 1234567890.12,
position: 42,
length: 150,
shortcut: 'Cmd+V',
content: 'The pasted text content...',
beforeText: 'Some existing text',
afterText: 'Some existing textThe pasted text content...',
replacedText: '', // Nothing was selected/replaced
replacedRange: undefined
}

Captures text selection actions.

interface SelectionEvent {
type: 'select';
timestamp: number;
startPosition: number;
endPosition: number;
selectedLength: number;
selectedText?: string; // The selected text content (omitted when privacy-sensitive)
method: 'mouse' | 'keyboard' | 'programmatic';
isTrusted?: boolean; // true if user-generated, false if scripted
}

Captures undo and redo operations.

interface UndoRedoEvent {
type: 'undo' | 'redo';
timestamp: number;
shortcut: string; // e.g., 'Ctrl+Z', 'Meta+Z'
beforeText: string;
afterText: string;
}

Detects text inserted without corresponding keystrokes, such as browser autocomplete, autofill, predictive text, AI extension injection, voice dictation, or programmatic value assignment.

interface ProgrammaticInsertionEvent {
type: 'programmatic-insertion';
timestamp: number;
insertedText: string; // Text that was inserted
insertedLength: number; // Character count
position: number; // Cursor position where text was inserted
isTrusted: boolean; // Whether the triggering input event was user-generated
inputType?: string; // InputEvent.inputType if available
inputSource?: InputSource; // Input source classification, set by editor integrations or beforeinput fallback
}

WriteTrack monitors text length changes against keystroke count. When text grows faster than keystrokes can explain, a programmatic insertion event is emitted.

Captures completed IME composition sequences (CJK input methods, dead keys, accent input). Intermediate keystrokes during composition are suppressed — only the final result is recorded.

interface CompositionEvent {
timestamp: number; // When the composition started
duration: number; // Duration of the composition sequence (ms)
insertedLength: number; // Characters inserted (0 if composition was abandoned)
isTrusted: boolean; // Whether the compositionend event was user-generated
}

Access captured events directly:

const keystrokes = tracker.getRawEvents();
const clipboard = tracker.getClipboardEvents();
const selections = tracker.getSelectionEvents();
const undoRedo = tracker.getUndoRedoEvents();
const insertions = tracker.getProgrammaticInsertionEvents();
const compositions = tracker.getCompositionEvents();

getData() returns the complete session as a WriteTrackDataSchema object:

const data = tracker.getData();
// {
// version: "2.1.0",
// metadata: { tool, targetElement, timestamp, duration },
// session: { events, clipboardEvents, selectionEvents, ... },
// quality: { overallScore, sequenceValid, qualityLevel, ... },
// }

Window focus changes are recorded as keystroke events:

{
key: 'FOCUS', // or 'BLUR'
code: 'FOCUS', // or 'BLUR'
type: 'keydown',
timestamp: 1234567890.12,
windowFocused: true, // or false
timeSinceLastMouse: 0
}

Document visibility changes (tab switching):

{
key: 'VISIBILITY_CHANGE',
code: 'VISIBILITY_CHANGE',
type: 'keydown',
timestamp: 1234567890.12,
windowFocused: false,
timeSinceLastMouse: 1234.5,
dwellTime: 5000 // Duration of visibility
}

WriteTrack uses performance.now() for high-precision timestamps:

  • Resolution: Sub-millisecond (typically 5μs)
  • Monotonic: Always increasing, not affected by system clock changes
  • Relative: Starts at 0 when the page loads
// Convert to absolute time if needed
const absoluteTime = Date.now() - performance.now() + event.timestamp;