Technical documentation / Ston Handoff
Installation, a step-by-step tutorial for every screen, the full settings reference and the architecture underneath — the complete documentation for Ston Handoff and the Pro add-on.
01 / At a glance
What makes Handoff different from hiding buttons in the editor.
Data level
Every write to _elementor_data is checked on the server — editor saves, REST, WP-CLI and other plugins included.
Every format
One document walker understands sections and columns, flexbox containers and atomic (V4) elements, so a lock survives a rebuild.
Safe rollout
Locks start in warning mode: design changes are logged but kept, so a lock never blocks legitimate work before you trust it.
Audit
Every structural change is recorded with user, element and the old and new value — with WordPress privacy export and erase.
Admin
Profiles hide menus, screens, widgets and notices. Hidden screens are also blocked by direct URL (HTTP 403).
Light
No front-end scripts or styles and no external calls. One option, autoload off, plus dedicated tables.
02 / Install
Download Ston Handoff from ston.ae/download/ston-handoff and upload it in Plugins → Add New → Upload. Activate it.
WordPress 6.6+, PHP 7.4 – 8.3 and Elementor (free is enough). A Handoff menu appears in the admin.
Upload Ston Handoff Pro next to the free plugin. Pro adds hard locks, content intake, CSV export, tips and a longer log.
Copy the key from My Account → Licenses on ston.ae and paste it on the License screen Pro adds under Handoff. Updates then arrive in Dashboard → Updates.
03 / Tutorial / Locks
Handoff → Locks lists every Elementor document. A lock is set per document.
Search for the page or template and open it. Bulk actions can lock several documents at once — bulk locks start in warning-only mode.
Content: only allowed props (text, images, links) can change. Frozen: no Elementor change is kept; title and excerpt stay editable in WordPress.
Click “Capture the current page as the new baseline”. Saving the page in Elementor as a designer refreshes it automatically.
Optional: list extra props per widget type for this document. Leave empty to use the site-wide list from Settings.
Log in as a client user, edit and save. Then tick “I tested editing and saving this document as a client”.
“Hard lock: revert locked changes on save”. Without it, violations are saved but logged — the free plugin always works this way.
At the bottom of Locks, lock Global design (Site Settings): global colors, fonts and classes change every page at once.
“Recent attempts” lists blocked changes per document. Frequent attempts mean the client needs an extra allowed prop.
04 / Tutorial / Profiles
Handoff → Profiles. A profile is a full configuration for one kind of client: menus, screens, dashboard, checklist, tips and support button.
“What should this user do?” — Only writes articles, Updates page content, or Adds products. The choice pre-selects what to hide next.
Tick menus and screens to hide. Hidden screens return 403 by direct URL; Dashboard and Profile always stay available.
Rename menu items, hide dashboard widgets and edit-screen metaboxes by ID, and take capabilities away when data must also be closed in REST or AJAX.
Simple client home instead of the dashboard, handover checklist, contextual tips (Pro), the “Ask for help” button, and hidden update or plugin notices.
The Client preview frame shows the real admin as the client sees it. Click around inside it before saving.
Search users by name or email and add them. A user belongs to one profile at a time; people who manage Handoff are never restricted.
05 / Tutorial / Handover
Handoff → Handover and Handoff → Settings.
Add steps or a task with a link. Built-in steps (log in, change password, first post) complete themselves. Progress is saved per user.
Agency name, brand color, logo, login URL and admin footer text — used across the client interface and the login page.
Settings → Support email. Requests and design change requests are sent there with technical context attached.
The “Ask for help” button sends the site, page, user, role and versions with the message — no back-and-forth to find out what they mean.
06 / Tutorial / Activity
Handoff → Activity, for users with the view-log capability.
Filter by user, document or action. Each row shows the time (UTC), element and the value before and after.
Settings → Activity log → Keep entries for (days). 30 by default; Pro raises the ceiling to 3650 days.
Download the filtered view as CSV (UTF-8 with BOM, opens correctly in Excel).
Log rows of a person are included in Tools → Export / Erase Personal Data.
07 / Tutorial / Content intake (Pro)
Handoff → Content intake. Send the client a link; their text and images land exactly where they belong.
New content request → name it (e.g. Home page content) and enter the client email, used for the invitation and reminders.
Each field maps to its destination: an ACF field (best for new projects) or an Elementor element (for sites already built). Set limits: max characters, min image size, max upload size.
Choose how long the link is valid (14 days by default) and email it. Reminders go out automatically (every 72 hours by default).
Open the submitted content, then Publish to site or Send back to client. Or tick “Publish automatically” to skip approval.
Email it again, create a new link (the old one stops working) or delete the request. A snapshot is taken before Handoff writes any content.
08 / Settings reference
Structure lock
Normal — each document follows its own hard-lock setting. Safe mode — every lock only warns and logs (use if a client cannot save).
Site-wide allowed props
JSON map of widget type → content props. Entries replace the default for that widget type. Atomic widgets use their own names, e.g. e-paragraph → paragraph.
Activity log
How many days entries are kept (default 30, up to 3650 with Pro).
Support email
Where support and design-change requests are sent.
Content intake (Pro)
Link validity (14 days), max upload size (5 MB) and reminder interval (72 hours).
Branding
Agency name, brand color (#EB1F27 by default), logo, login URL, admin footer text.
Delete data on uninstall
Off by default. When on, locks, log, content requests and settings are deleted with the plugin.
09 / Architecture
One layer understands Elementor. The other does not have to — it sits under every write to the protected meta keys.
Layer 1
Runs on elementor/document/save/data and on the editor’s ajax return. The incoming tree is walked and compared element by element.
Scope: editor saves, autosaves, template applies.
Layer 2
Runs on update_post_metadata, add_post_metadata and delete_post_metadata for the protected keys.
Scope: REST, WP-CLI, cron, other plugins.
10 / Save pipeline
editor save
REST request
direct meta write
occurrence keys (id, id#2)
type + parent + order
layout props only
revert structure
keep content edits
write audit entry
Diffing by occurrence key rather than by element id defeats the duplicate-id bypass: two nodes sharing an id no longer look like one. An unparseable incoming tree is rejected; only an unparseable baseline downgrades the lock to a warning, so a corrupt snapshot can never silently unlock a page.
11 / Scope
—
adding or removing sections, containers, widgets
—
reordering elements; changing an element type
—
width, padding, margin, gap, alignment
—
column and grid structure
—
page template and layout settings
—
headings, paragraphs, rich text
—
images, alt text, links
—
button labels and URLs
—
any property on the allow list
—
everything on unlocked documents
12 / Data model
A single document walker normalises the three element formats Elementor has shipped, so a lock captured today survives a rebuild with containers or atomic elements.
_elementor_data
element tree — diffed and reverted
_elementor_page_settings
layout keys protected
_elementor_edit_mode
protected against downgrade
elementor_active_kit
site-wide styles watched
legacy section / column
supported
flexbox container
supported
atomic V4 ($$type envelopes)
supported
13 / Capabilities
ston_handoff_manage
Create and release locks, edit profiles, change settings. Administrator by default.
ston_handoff_bypass_lock
Edits pass through untouched — the capability you keep for yourself.
ston_handoff_view_log
Read the change log; rows for documents the user cannot edit stay hidden.
ston_handoff_approve_intake
Review and publish content the client submitted through an intake link.
14 / Logging
recorded per entry
time (UTC), user, action, document, element, before, after
retention
7 – 30 days by default, up to 3650 days with the add-on
purge
daily cron, deletes in bounded batches
export
CSV of the filtered view (add-on), UTF-8 with BOM
privacy
WordPress export and erase tools supported
blocked attempts
listed per document on the Locks screen
15 / Extension points
The add-on is written entirely on top of these; your own snippets can use the same surface, so nothing needs patching.
ston_handoff_enforcement_available
filter — may locks revert changes
ston_handoff_support_context
filter — attach data to a support request
ston_handoff_log_retention_max
filter — raise the retention ceiling
ston_handoff_ignored_post_types
filter — keep a post type out of the log
ston_handoff_admin_pages
filter — add a submenu screen
ston_handoff_admin_notices
filter — register notice codes
ston_handoff_overview_stats
filter — add a stat card
ston_handoff_settings_sections
action — render a settings block
ston_handoff_handover_sections
action — render a handover card
ston_handoff_activity_actions
action — add controls above the log
ston_handoff_pro_url
filter — change the add-on link
ston_handoff_loaded
action — the plugin finished booting
16 / Server footprint
{prefix}ston_handoff_locks
baselines and lock settings
{prefix}ston_handoff_log
change log entries
{prefix}ston_handoff_intake
content requests (add-on)
ston_handoff_settings
one option, autoload off
ston_handoff_purge_audit_log
daily cron — log retention
ston_handoff_intake_reminders
hourly cron (add-on)
uploads/ston-handoff-intake-<key>/
private folder, .htaccess + index.php
ston_handoff_tip
hidden post type for in-dashboard tips (add-on)
front-end assets
none — enforcement runs on save
17 / Failure behaviour
add-on inactive
locks fall back to watch mode; nothing is deleted
baseline unparseable
lock downgrades to a warning, save is allowed
incoming tree unparseable
save is rejected, entry written to the log
user has bypass capability
change passes through, still logged
document unlocked
no comparison, no log entry
plugin deactivated
data stays; enforcement stops immediately
uninstall
data removed only if you opted in beforehand
Uninstall order matters: turn on “remove data” in Settings first, then delete the add-on, then the free plugin. The add-on reads that setting from the free plugin’s option, so removing the free plugin first leaves the add-on’s data in place.
18 / Troubleshooting
The client cannot save
Switch Settings → Structure lock to Safe mode, then check Recent attempts on the document to see which change was blocked.
A text change was reverted
The prop is not on the allow list. Add it for that widget type in Settings, or per document on its lock screen.
Design changes are kept
Without Pro, locks only watch and log. With Pro, turn on “Hard lock” for the document.
The lock shows a warning
The baseline could not be read. Capture a new baseline; the lock never unlocks silently.
A menu is still visible
Users who can manage Handoff are never restricted. Test with a real client account or in Client preview.
Intake link does not open
The link expired or a new link was created. Create a new link from the request.
19 / Requirements