Validation and Sanitization in the Customizer

At Automattic, we exclusively use the Customizer for theme options instead of theme option pages. We believe that themes should only alter the display of content and should not add any additional functionality that would be better suited for a plugin. Since all options are presentation centered, they should all be controllable by the Customizer.

The callback will only be called when the setting is saved to the database. If you use the refresh method to update the preview, sanitization is complete.

In our case, since we opted to use the postMessage method of updating the preview, we would have to validate (and sanitize) the the value in the corresponding JavaScript file, too.

In many cases it is not even necessary to define a custom callback function. In cases where you want to sanitize a URL or an email address for example, you can pass 'esc_url_raw' or 'is_email' directly:

I hope you now have a better understanding of how to write more secure code when dealing with the Customizer. It’s a great tool for users and theme developers alike, and I am very excited about the opportunities it creates.

13 thoughts on “Validation and Sanitization in the Customizer”

– sanitize_callback and sanitize_js_callback are good, but I believe were added after I wrote those tutorials, which is why I don’t mention them. I should probably do a new writeup about them.

– If you’re using actual Settings (and not the theme-mods system), then you have the option to specify a $sanitize_callback function name as the third parameter to the register_setting() function call. This callback will be called anytime that option is updated in the database. This includes via the customizer. This is a safer approach than using pre_update_option_$option to deal with it.

– If you are using theme mods, then hooking to sanitize_option_theme_mods_$theme is probably the better hook to use, because, well, it has sanitize right in the name, and that’s where sanitization stuff is intended to hook in. Although realistically, and for sanity’s sake, I’d suggest using the individual setting’s callbacks in add_setting instead. Safer, less bug-prone, even if it is a bit more typing and such. And as you point out, a lot of those type of sanitization functions you can get for free by using the built in functions.

Thanks so much for your feedback Otto! Nacin told me yesterday about how register_settings() is more appropriate for option sanitization – I never thought of connecting the Settings API and the Customizer like that.

I checked the file wp-includes/formatting.php and it seems that both functions do pretty much the same checking for the email. Naturally is_email() returns false if it doesn’t pass the check and sanitize_email() returns filtered email address.

If you execute this code, you can see that öttö@wördpräss.com is not a valid email adress, but sanitize_email() returns … ehmmm… some chars.
This code would lead you into trouble if you depend on the result by sanitize_email():
wp_mail( sanitize_email( $email ), 'Testmail', 'A testmessage' );

But in theme Customizer we’re not sending any emails, at least I’m not. For me it’s just for gravatar email so I don’t mind if öttö@wp.com gets to tt@wp.com. User will notice this right away in live preview.

But then again I could check is_email first and if it fails I could place invalid email in text field. That might be even more user friendly.

If you’re using actual Settings (and not the theme-mods system), then you have the option to specify a $sanitize_callback function name as the third parameter to the register_setting() function call. This callback will be called anytime that option is updated in the database. This includes via the customizer. This is a safer approach than using pre_update_option_$option to deal with it.

Sorry, but I’m a bit unclear here as to whether the sanitize_callback can be used with theme-mods system. This (quoted above) seems to suggest no, but the example(s) code seems to default to the theme_mod since type (type => option) argument in not used in any of these.