Docs/Developer Guide/Best Practices
Best Practices
A short checklist that prevents most of what shows up in FAQ.
Use the read helper that matches the storage type
Option panel field → tpmeta_get_option() / get_theme_mod(). Metabox field → tpmeta_field(). Mixing these up is the most common "my value is empty" report — see Introduction → How the plugin works.
Pick a field ID once, then don't change it
The id is the literal storage key. Renaming it after a site has saved data orphans that data. Keep IDs short, lowercase, and prefixed for your project (mytheme_hero_title) to avoid collisions with other plugins/themes.
Use boolean switches for new fields
Set data_type => 'boolean' on switch fields so tpmeta_get_option() returns a real PHP bool. A string-based switch stores 'false', which is truthy in PHP and breaks a plain if() check.
Register option panels on init, priority 5
Both set_args() and set_section() must run at or before priority 5 on init — the same hook the builder's loader uses. Registering later means the admin menu never appears.
Escape on output, always
Read helpers return raw stored values. Use esc_html() for text, esc_url() for URLs/images, and esc_attr() for HTML attributes. The editor type stores HTML — output it through wp_kses_post(), not raw echo.
Guard array values before sanitizing as text
If you add a custom sanitize_callback to a field, check is_array() before calling sanitize_text_field() on a value — composite field types (repeater, gradient, multicolor) store arrays, not strings, and passing an array where a string is expected raises a PHP notice.
Check the field's ID matches the conditional rule's controller
A conditional rule's controller field must live in the same section (options) or the same metabox/repeater row as the dependent field. See Advanced Topics → Dynamic Data.