Skip to content

TipTap Integration

WriteTrack includes a first-party TipTap extension, compatible with @tiptap/core v2.0+ and tested against v3.19. See React and Vue examples below.

Install WriteTrack alongside your TipTap packages:

Terminal window
npm i writetrack @tiptap/core @tiptap/starter-kit
import { Editor } from '@tiptap/core';
import StarterKit from '@tiptap/starter-kit';
import { WriteTrackExtension } from 'writetrack/tiptap';
const editor = new Editor({
element: document.querySelector('#editor'),
extensions: [
StarterKit,
WriteTrackExtension.configure({
license: 'your-license-key',
}),
],
});
// Access WriteTrack data when needed
const data = editor.storage.writetrack.tracker.getData();

Pass options via .configure():

WriteTrackExtension.configure({
license: 'your-license-key',
userId: 'user-123',
contentId: 'document-456',
metadata: { formName: 'signup' },
autoStart: true, // default
});
OptionTypeDefaultDescription
licensestringundefinedWriteTrack license key
userIdstringundefinedUser identifier included in metadata
contentIdstringundefinedContent identifier included in metadata
metadataRecord<string, unknown>undefinedAdditional metadata
autoStartbooleantrueStart tracking when editor is created
wasmUrlstringundefinedURL to WASM binary for analysis
persistbooleanfalseEnable IndexedDB session persistence (requires contentId)

The extension stores the WriteTrack instance in TipTap’s storage system:

// Get the tracker instance
const tracker = editor.storage.writetrack.tracker;
// Get typing data
const data = tracker.getData();
// Check tracking status
const isTracking = editor.storage.writetrack.isTracking;
import { useEditor, EditorContent } from '@tiptap/react';
import StarterKit from '@tiptap/starter-kit';
import { WriteTrackExtension } from 'writetrack/tiptap';
const writetrack = WriteTrackExtension.configure({
license: 'your-license-key',
});
function FormEditor() {
const editor = useEditor({
extensions: [StarterKit, writetrack],
});
const handleSubmit = () => {
const data = editor?.storage.writetrack.tracker?.getData();
console.log('Typing data:', data);
};
return (
<div>
<EditorContent editor={editor} />
<button onClick={handleSubmit}>Submit</button>
</div>
);
}
<script setup>
import { useEditor, EditorContent } from '@tiptap/vue-3';
import StarterKit from '@tiptap/starter-kit';
import { WriteTrackExtension } from 'writetrack/tiptap';
const writetrack = WriteTrackExtension.configure({
license: 'your-license-key',
});
const editor = useEditor({
extensions: [StarterKit, writetrack],
});
function handleSubmit() {
const data = editor.value?.storage.writetrack.tracker?.getData();
console.log('Typing data:', data);
}
</script>
<template>
<div>
<EditorContent :editor="editor" />
<button @click="handleSubmit">Submit</button>
</div>
</template>

If you prefer not to use the extension, you can attach WriteTrack directly to TipTap’s editable element:

import WriteTrack from 'writetrack';
import { Editor } from '@tiptap/core';
import StarterKit from '@tiptap/starter-kit';
const editor = new Editor({
element: document.querySelector('#editor'),
extensions: [StarterKit],
onCreate({ editor }) {
const tracker = new WriteTrack({
target: editor.view.dom,
license: 'your-license-key',
});
tracker.start();
},
});
import type {
WriteTrackExtensionOptions,
WriteTrackExtensionStorage,
} from 'writetrack/tiptap';