Saved Blocks and Synced Sections
Topol provides two powerful features for reusing content across your email templates:
Saved Blocks - Save any section or content block and reuse it across multiple templates. When you insert a saved block, it creates a copy that you can edit independently.
Synced Sections - Save sections that stay synchronized across all templates. When you edit a synced section, the changes are automatically reflected everywhere it's used.
Enabling Saved Blocks
Users can save their structures by clicking "Save as Block" button while the structure they want to save is selected.

To enable this feature, set savedBlocks to an empty array.
savedBlocks: [],To disable it, set savedBlocks to null.
savedBlocks: null,You can also hide saved blocks by setting savedBlocks to false.
savedBlocks: false,Each saved block within the savedBlocks array is an object and has the following structure:
{
id: 1, // ID of the block, if not set it uses the Array Index
name: 'My saved block 001', // You can set a name or an image
img: 'http://...', // The editor shows only name or image, not both, if both set it will show the image
definition: 'json' // JSON of this saved block
},Enabling Synced Sections
To enable synced sections, set syncedSectionsEnabled to true:
syncedSectionsEnabled: true,When synced sections are enabled, users can save structures as synced by clicking "Save as Synced structure" in the section actions menu. Unlike regular saved blocks, synced sections maintain a live connection to all templates where they're used - editing a synced section updates it everywhere.
Advanced Configuration
There are three actions you need to implement to make saved blocks work:
onBlockSaveonBlockEditonBlockRemove
All of them needs to be implemented in the callbacks object.
Example:
callbacks: {
onBlockSave(json) {
const name = window.prompt('Enter block name:')
if (name !== null) {
console.log('saving block', json)
}
},
onBlockRemove(id) {
if (window.confirm('Are you sure?')) {
console.log('removing block', id)
}
},
onBlockEdit(id) {
const name = window.prompt('Block name:', 'My block 001')
if (name !== null) {
console.log('saving edited block', id)
}
}
}Since it's your responsibility to handle those actions, you also need to update the list of saved blocks once they are updated. To do this, you can use the TopolPlugin.setSavedBlocks([savedBlocks]) function.
This function takes an array of all saved blocks you want to display in the editor.
TopolPlugin.setSavedBlocks([
{
id: 1, // ID of the block, if not set it uses the Array Index
name: "My saved block 001", // You can set a name or an image
img: "http://...", // The editor shows only name or image, not both, if both set it will show the image
definition: "json", // JSON of this saved block
},
]);API-Based Configuration
For a more advanced setup, you can use the API-based feature. This allows you to store saved blocks and synced sections on your server with support for folders, search, pagination, and preview images.
To enable API-based saved blocks and synced sections, set savedBlocks to true and configure the api.SAVED_SECTIONS endpoint:
const TOPOL_OPTIONS = {
savedBlocks: true,
syncedSectionsEnabled: true, // Enable synced sections
api: {
SAVED_SECTIONS: "https://your-domain.com/saved-blocks",
},
};Both saved blocks and synced sections use the same API.SAVED_SECTIONS endpoint. They are differentiated by the type field in the API responses and requests.
Before implementing the endpoints check how to work with API endpoints
List Saved Blocks, Synced Sections and Folders
Request
- URL:
/{API.SAVED_SECTIONS} - Method:
GET - Content-Type:
application-json
Params:
| key | value | required |
|---|---|---|
| key | authorization api key | true |
| hostname | hostname | true |
| entity_id | entity_id corresponds to userId in Options | true |
| per_page | number of items per page | false |
| current_page | number of page to return | false |
| sort_by | "name" or "date" or "type" | false |
| desc | "true" | false |
| folder_id | id of folder to return | false |
| search | string to search | false |
| type | "saved_section" or "synced_section" to filter by type | false |
This endpoint is called when the editor lists all saved blocks/synced sections, changes sort, page or folder, searches by string, or when you call TopolPlugin.refreshSyncedSections().
Response
{
"success": true,
"data": {
"data": [
{
"id": 1,
"name": "name of saved block, synced section, or folder",
"type": "saved_section" or "synced_section" or "folder",
"created_at": "ISO 8601 time",
"definition": "json of MJML section",
"image": "https://url-to-preview-image.jpg",
"folder_id": 2
}
],
"lastPage": 5,
"parentFolderId": null
}
}Create Saved Block, Synced Section or Folder
- URL:
/{API.SAVED_SECTIONS} - Method:
POST
This endpoint is called when a new saved block, synced section, or folder is created.
Request
{
"entity_id": "entity user_id",
"hostname": "origin",
"key": "api key",
"type": "saved_section" or "synced_section" or "folder",
"name": "name of new item",
"definition": "json of MJML section",
"folder_id": 1
}Response
STATUS 200
{
"success": true,
"data": {
"id": 2,
"name": "name of saved block, synced section, or folder",
"type": "saved_section" or "synced_section" or "folder",
"created_at": "ISO 8601 time",
"definition": "json of MJML section",
"folder_id": 1
}
}Get Saved Block or Synced Section Detail
Request
- URL:
/{API.SAVED_SECTIONS}/{id} - Method:
GET - params:
key,hostname,entity_id
This endpoint is called when inserting a saved block into a template. For synced sections, it is also called when loading a template that contains synced sections to ensure the latest content is displayed.
Response
STATUS 200
{
"success": true,
"data": {
"id": 1,
"name": "name of saved block or synced section",
"type": "saved_section" or "synced_section",
"created_at": "ISO 8601 time",
"definition": "json of MJML section",
"folder_id": 2
}
}Edit Saved Block, Synced Section or Folder
Request
- URL:
/{API.SAVED_SECTIONS}/{id} - Method:
PATCH
This endpoint is called when editing the name, content, or folder location of a saved block, synced section, or folder.
{
"entity_id": "entity user_id",
"hostname": "origin",
"key": "api key",
"folder_id": 1,
"definition": "json of MJML section",
"name": "edited name"
}Response
STATUS 200
Delete Saved Blocks, Synced Sections or Folders
- URL:
/{API.SAVED_SECTIONS}/delete - Method:
POST
This endpoint is called when the user deletes saved blocks, synced sections, or folders. For synced sections, the last loaded version remains in templates where it was used.
Request
{
"entity_id": "entity user_id",
"hostname": "origin",
"key": "api key",
"blocksToDelete": [1, 2, 3]
}Response
STATUS 200
Refresh Synced Sections
Call the refreshSyncedSections function on the TopolPlugin instance to update the synced sections listing and reload the template with the latest changes.
TopolPlugin.refreshSyncedSections();This is useful when multiple users are working in the editor simultaneously - whether in the same template or different ones. If someone else creates, edits, or deletes a synced section, calling this function ensures your view stays up to date.
Preview Images
When creating a saved block or synced section, you can store a preview image on your server. The editor sends the block definition, and you can generate a preview image from it. Return the image URL in the image field when listing items.
Multi-language Support
If you're using multilingual templates, saved blocks and synced sections can include translations. The translation field contains language-specific content:
{
"id": 1,
"name": "Header Block",
"type": "saved_section",
"definition": "json of MJML section",
"translation": {
"en": { ... },
"de": { ... }
}
}