# Track changes overview

The track changes feature (also known as suggestion mode) records edits as suggestions marked in the content instead of applying them directly. Reviewers can then follow who changed what and accept or decline each suggestion individually or all at once. It works both as a standalone plugin and as part of real-time collaboration.

> **Unlock this feature with selected CKEditor Plans**
>
> Try all premium features – no credit card needed.
>
> [Sign up for a free trial ](https://portal.ckeditor.com/checkout?plan=free)[Select a Plan](https://ckeditor.com/pricing/)

<a id="demo">

## Demo

You can test the track changes feature in the editor below. Use the toolbar dropdown to enable changes tracking and mass accept or decline suggestions. Use the side panel to work with individual changes.

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

This demo presents a limited set of features. Visit the [feature-rich editor example](../../../examples/builds-custom/full-featured-editor.md) to see more in action.

In this mode, changes done by the users are marked in the content and shown as suggestions in the sidebar. Suggestions can be accepted or discarded by the users. The suggestion balloon is then closed and the change is no longer marked.

> **Note**
>
> Suggestion annotations can be displayed in a sidebar or as inline balloons. Visit the [display mode](../annotations/annotations-display-mode.md) guide to learn how to configure the display mode. The mode specified for comments is also set for track changes.
>
> This sample automatically switches between display modes according to the screen size. Resize the window and observe how the editor changes its appearance.

Apart from reading this guide, we encourage you to read a dedicated blog post which [compares the track changes with revision history](https://ckeditor.com/blog/ckeditor-5-comparing-revision-history-with-track-changes/) and another blog post discussing [CKEditor 5’s collaboration features and their real-life implementations](https://ckeditor.com/blog/Feature-of-the-month-Collaborative-writing-in-CKEditor-5/).

<a id="integration">

## Integration

<a id="use-as-a-standalone-plugin">

### Use as a standalone plugin

The track changes feature does not require real-time collaboration to work. If you prefer a more traditional approach to document editing, track changes can be added to CKEditor 5 just like any other plugin.

To learn how to integrate track changes as a standalone plugin, please refer to the [Integrating track changes with your application](track-changes-integration.md) guide.

<a id="use-with-real-time-collaboration">

### Use with real-time collaboration

If you are using the real-time collaboration feature, refer to the [Real-time collaboration features integration](../real-time-collaboration/real-time-collaboration-integration.md) guide.

<a id="learn-more">

## Learn more

After you run the track changes feature in your editor, you may want to learn more about it. Find out below how it works, how it can be configured, customized, and extended, to fit your application the best way possible.

<a id="configuration">

### Configuration

The configuration for the track changes feature can be found in the [`TrackChangesConfig`](../../../api/module_track-changes_trackchangesconfig-TrackChangesConfig.md) API reference.

<a id="suggestions-markup">

### Suggestions markup

Suggestions are always attached to some place in the document. To make sure that they will not be lost, the track changes plugin adds some special markup to the document:

* `<suggestion-start>` and `<suggestion-end>` tags are added if the suggestion starts/ends in text,

* otherwise, the following attributes are added to elements:

  * `data-suggestion-start-before`,
  * `data-suggestion-end-after`,
  * `data-suggestion-start-after`,
  * `data-suggestion-end-before`.

Also, the `<suggestion-td>` tag is used for table cells pasting suggestions to separate old content (original) from the new content (pasted).

[Read more about marker-to-data conversion](../../../api/module_engine_conversion_downcasthelpers-DowncastHelpers.md#function-markerToData) to understand what data you may expect.

Examples of the possible markup:

Replacing the word “chocolate” with the word “ice-cream”:

```html
<p>
	I like
	<suggestion-start name="insertion:e8ghd7:e390dk"></suggestion-start>ice-cream<suggestion-end name="insertion:e8ghd7:e390dk"></suggestion-end>
	<suggestion-start name="deletion:ejd853:e390dk"></suggestion-start>chocolate<suggestion-end name="deletion:ejd853:e390dk"></suggestion-end>.
</p>
```

Inserting image:

```html
<figure class="image" data-suggestion-end-after="insertion:e1f0810:eohfu9" data-suggestion-start-before="insertion:e1f0810:eohfu9">
	<img src="foo.jpg">
	<figcaption>Image caption.</figcaption>
</figure>
```

Adding bold:

```html
<p>
	This is
	<suggestion-start name="attribute:bold|ci1tcnk0lkep:ekeij:e3404"></suggestion-start>
	<strong>important</strong>
	<suggestion-end name="attribute:bold|ci1tcnk0lkep:ekeij:e3404"></suggestion-end>
	.
</p>
```

Pasting a table cell with the text “New” into a table cell with the text “Old”:

```html
<td ...>
	<suggestion-td data-suggestion-end-after="insertion:..." data-suggestion-start-before="insertion:...">
		<p>New</p>
	</suggestion-td>
	<suggestion-td data-suggestion-end-after="deletion:..." data-suggestion-start-before="deletion:...">
		<p>Old</p>
	</suggestion-td>
</td>
```

Note that if your application filters HTML content, for example, to prevent XSS, make sure to leave the suggestion tags and attributes in place when saving the content in the database. The suggestion markup is necessary for further editing sessions.

<a id="suggestions-attributes">

### Suggestions attributes

Suggestion attributes is additional data stored with the suggestions and used by other features. You can also use them to set and read custom data necessary by your custom features built around suggestions.

```ts
suggestion.setAttribute( 'isImportant', true );
```

You can group multiple values in an object, using dot notation:

```ts
suggestion.setAttribute( 'customData.type', 'image' );
suggestion.setAttribute( 'customData.src', 'foo.jpg' );
```

Attributes set on the suggestion can be accessed through `attribute` property:

```ts
const isImportant = suggestion.attributes.isImportant;
const type = suggestion.attributes.customData.type;
```

You can also observe `attributes` property or bind other properties to it:

```ts
myObj.bind( 'customData' ).to( suggestion, 'attributes', attributes => attributes.customData );
```

Whenever [`setAttribute()`](../../../api/module_track-changes_suggestion-Suggestion.md#function-setAttribute) or [`removeAttribute()`](../../../api/module_track-changes_suggestion-Suggestion.md#function-removeAttribute) is called, the `attributes` property is re-set, and observables are refreshed. Using these fires the `update` method in an adapter.

<a id="saving-the-data-without-suggestions">

### Saving the data without suggestions

If you need to get the editor data with all the existing suggestions accepted or discarded, please refer to the [dedicated guide](track-changes-data.md).

<a id="saving-the-data-with-suggestion-highlights">

### Saving the data with suggestion highlights

By default, the data returned by `editor.getData()` contains the markup for the suggestions as described above. It does not provide the markup that visually shows the suggestion highlights in the data (similarly to how they are shown in the editor).

It is possible to change the editor output using the `showSuggestionHighlights` option passed in `editor.getData()`. When set, the editor output will return suggestions similarly to how they are present inside the editor:

```js
editor.getData( { showSuggestionHighlights: true } );
```

Will return:

```html
<p>
	<span class="ck-suggestion-marker ck-suggestion-marker-formatInline">
		Foo
	</span>
	bar
</p>
```

> **Note**
>
> The output data generated using the `showSuggestionHighlights` option cannot be used to load the editor data (it cannot be passed to `editor.setData()`)!
>
> This feature should be used for preview purposes and can be used, for example, together with the [export to PDF feature](../../converters/export-pdf.md).

The [export to PDF feature](../../converters/export-pdf.md) can be integrated with the suggestion highlights as shown below:

```js
{
	exportPdf: {
		// More configuration of the Export to PDF.
 		// ...
		dataCallback: editor => editor.getData( {
			showSuggestionHighlights: true
		} )
	}
}
```

<a id="force-track-changes-mode-to-be-enabled">

### Force track changes mode to be enabled

If you would like to have track changes enabled by default, execute the `trackChanges` command, which toggles the track changes mode. It should be done after the editor instance is initialized:

```js
ClassicEditor
	.create( {
	   // Editor's configuartion.
 		// ...
	} )
	.then( editor => {
		editor.execute( 'trackChanges' );
	} )
	.catch( error => console.error( error ) );
```

You can disable the `trackChanges` command to prevent turning the track changes on or off. This can be useful for example when a particular user has permissions only to create suggestions in a given document. You can disable the command by calling [`Command#forceDisabled()`](../../../api/module_core_command-Command.md#function-forceDisabled):

```js
ClassicEditor
	.create( {
		// Editor's configuartion.
		// ...
	} )
	.then( editor => {
		editor.execute( 'trackChanges' );

		editor.commands.get( 'trackChanges' ).forceDisabled( 'suggestionsMode' );
	} )
	.catch( error => console.error( error ) );
```

To prevent a user from accepting or discarding suggestions, disable commands responsible for these actions:

```js
ClassicEditor
	.create( {
		// Editor's configuartion.
		// ...
	} )
	.then( editor => {
		editor.execute( 'trackChanges' );

		editor.commands.get( 'trackChanges' ).forceDisabled( 'suggestionsMode' );
		editor.commands.get( 'acceptSuggestion' ).forceDisabled( 'suggestionsMode' );
		editor.commands.get( 'acceptAllSuggestions' ).forceDisabled( 'suggestionsMode' );
		editor.commands.get( 'discardAllSuggestions' ).forceDisabled( 'suggestionsMode' );
		editor.commands.get( 'discardSuggestion' ).forceDisabled( 'suggestionsMode' );
	} )
	.catch( error => console.error( error ) );
```

Keep in mind that the `'suggestionsMode'` identifier can be later used to enable commands using [`Command#clearForceDisabled()`](../../../api/module_core_command-Command.md#function-clearForceDisabled).

<a id="markers-styling">

### Markers styling

Similarly to everywhere in the CKEditor 5 Ecosystem, we have used [CSS Variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables) to let the developers customize the design of such UI elements as, for example, suggestion markers. You can override these properties with a `.css` file or place your customizations directly into the `<head>` section of your page, but in this case, you will need to use a more specific CSS selector than `:root` (like `<body>`).

> **Note**
>
> Check out the [color sheet](https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-ui/theme/globals/_colors.css) for the full list of customizable colors. You can also browse [other files](https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor5-ui/theme/globals) with CSS Variables in CKEditor 5.

Here you can find the default CSS Variables used for the track changes feature:

```css
:root {
	/* You can override the design of suggestion markers in the content. */

	/* Variables responsible for suggestions for text: */
	--ck-color-suggestion-marker-insertion-border: hsla(128, 71%, 40%, .35);
	--ck-color-suggestion-marker-insertion-border-active: hsla(128, 71%, 25%, .5);
	--ck-color-suggestion-marker-insertion-background: hsla(128, 71%, 65%, .35);
	--ck-color-suggestion-marker-insertion-background-active: hsla(128, 71%, 50%, .5);

	--ck-color-suggestion-marker-deletion-border: hsla(345, 71%, 40%, .35);
	--ck-color-suggestion-marker-deletion-border-active: hsla(345, 71%, 25%, .5);
	--ck-color-suggestion-marker-deletion-background: hsla(345, 71%, 65%, .35);
	--ck-color-suggestion-marker-deletion-background-active: hsla(345, 71%, 50%, .5);
	--ck-color-suggestion-marker-deletion-stroke: hsla(345, 71%, 20%, .5);

	--ck-color-suggestion-marker-format-border: hsla(191, 90%, 40%, .4);
	--ck-color-suggestion-marker-format-border-active: hsla(191, 90%, 40%, .65);

	/* Variables responsible for the left border of the suggestion boxes in the sidebar: */
	--ck-color-comment-box-border: hsl(55, 98%, 48%);
	--ck-color-suggestion-box-deletion-border: hsl(345, 62%, 60%);
	--ck-color-suggestion-box-insertion-border: hsl(128, 62%, 60%);
	--ck-color-suggestion-box-format-border: hsl(191, 62%, 60%);

	/* Variables responsible for the styling of suggestions for widgets: */
	--ck-color-suggestion-widget-insertion-background: hsla(128, 71%, 65%, .05);
	--ck-color-suggestion-widget-insertion-background-active: hsla(128, 71%, 50%, .07);
	--ck-color-suggestion-widget-deletion-background: hsla(345, 71%, 65%, .05);
	--ck-color-suggestion-widget-deletion-background-active: hsla(345, 71%, 45%, .07);
	--ck-color-suggestion-widget-format-background: hsla(191, 90%, 40%, .09);
	--ck-color-suggestion-widget-format-background-active: hsla(191, 90%, 40%, .16);

	--ck-color-suggestion-widget-th-insertion-background: hsla(128, 71%, 65%, .1);
	--ck-color-suggestion-widget-th-insertion-background-active: hsla(128, 71%, 50%, .12);
	--ck-color-suggestion-widget-th-deletion-background: hsla(345, 71%, 65%, .1);
	--ck-color-suggestion-widget-th-deletion-background-active: hsla(345, 71%, 45%, .12);
}
```

<a id="clipboard-integration">

### Clipboard integration

When you copy, cut or drag\&drop content containing suggestions, all selected content will be kept in the clipboard pipeline as-is in the editor, meaning that e.g. content in deletion suggestions will be retained.

This behavior can be changed using the [`config.trackChanges.clipboardMode`](../../../api/module_track-changes_trackchangesconfig-TrackChangesConfig.md#member-clipboardMode) configuration option. If you set it to `accept`, clipboard pipeline will automatically accept most suggestions, so the clipboard will contain content as if suggestions were accepted.

Note, that there’s a limitation regarding some block format suggestions (e.g. blockquote or code block) - these suggestions cannot be automatically accepted in clipboard and will be dropped.

<a id="api-overview">

### API overview

Check the [track changes API documentation](../../../api/track-changes.md) for detailed information about the track changes API. Making yourself familiar with the API may help you understand the code snippets.

<a id="suggestions-annotations-customization">

### Suggestions annotations customization

The suggestions annotations are highly customizable. Please refer to the [Annotation customization](../annotations/annotations.md) guide to learn more.

<a id="integration-with-custom-features">

### Integration with custom features

If you provide your own plugins, you may want to [integrate these custom features with track changes mode](track-changes-custom-features.md).

---

Full index of the CKEditor 5 documentation: [llms.txt](../../../../llms.txt)
