Understanding the block:modified Callback in Unlayer's Custom Blocks API
If you've worked with Unlayer's custom blocks JavaScript API, you may have noticed that the block:modified callback doesn't return the full block JSON, only the category and tags. This article clarifies why that is the case, what block:modified is actually for, and how it differs from block:added.
What Triggers block:modified
The block:modified callback is triggered when a user clicks the three-dot context menu on an existing block in the Blocks panel and updates its metadata through the modal that appears. That modal only allows the user to change the block's category and tags, nothing else. As a result, the callback only returns those fields: id, category, and tags.
Is This Expected Behavior?
Yes, this is by design, at least for regular (non-synced) custom blocks. The payload passed to block:modified intentionally excludes the block's design data. The full block content is only included in the payload for Synced Blocks, which follow a different internal code path.
How block:modified Differs from block:added
These two callbacks serve fundamentally different purposes in the block lifecycle:
block:added fires when a user selects a row on the canvas and saves it as a new block. It returns the complete block JSON including the design data, category, tags, display mode, and schema version. This is the callback to use when persisting a new block to your server.
block:modified fires when a user edits the category or tags of an already-saved block through the three-dot menu. It only returns the fields that can change through that UI. The intended use case is syncing metadata changes back to your server, for example when a user recategorizes a block from "Headers" to "Footers" or adds new search tags.
block:removed fires when a user deletes a block via the three-dot menu, and returns only the userId and id.
The Intended Self-Hosted Block Workflow
block:added -> INSERT the new block in your database (full JSON) block:modified -> UPDATE only the category/tags for an existing block (by id)
block:removed -> DELETE the block from your database (by id)
Can You Retrieve the Full Block JSON from block:modified?
No, not for regular custom blocks. The payload is constructed before the callback fires and does not include the data field. There is no mechanism within the callback itself to request the full block content.
If your use case involves a user loading an existing block onto the canvas, editing it, and re-saving it, that flow goes through block:added, not block:modified. Saving a row as a block always triggers the block creation path, making block:added your update mechanism as well.
If you need to correlate a block:modified call with the full block data, use the id from the callback to look it up in your own database where you stored it when block:added originally fired.
When to Use Each Callback
Use block:added when you need to capture or store the full content of a block, whether it's being saved for the first time or re-saved after edits on the canvas.
Use block:modified only when you need to keep your server's metadata in sync after a user changes a block's category or tags through the three-dot menu.
