How to render ACF Wysiwyg fields correctly

Advanced Custom Fields (ACF) allows you to add a WYSIWYG field, like the WordPress visual editor, as a custom field on your pages or posts. When you’re editing this field in the backend, you can apply formatting and styles as you normally would in the post editor.

When you come to output the field, however, you may find that if you’re using get_post_meta to look it up, any special formatting you’ve applied may be gone.

To get around this issue, I like to create a new filter called meta_content which we can apply to our custom post field. The idea here is that we utilize all of the functionality normally applied with the the_content filter to present our Wysiwyg field properly. Adding the following code to your functions file or plugin will make this filter available for use in your template files.

* Create new 'meta_content` filter.
* Recreate the default filters applied to `the_content`,
* so content retrieved using `get_post_meta` can be
* formatted in the same way.
add_filter( 'meta_content', 'wptexturize' );
add_filter( 'meta_content', 'convert_smilies' );
add_filter( 'meta_content', 'convert_chars' );
add_filter( 'meta_content', 'wpautop' );
add_filter( 'meta_content', 'shortcode_unautop' );
add_filter( 'meta_content', 'prepend_attachment' );
view raw functions.php hosted with ❤ by GitHub

From there on, you can look up your custom field as normal, using:

$field = get_post_meta( get_the_ID(), 'field_name', true );

And then when you want to output it, simply apply our filter, like so:

echo apply_filters( 'meta_content', wp_kses_post( $field ) );

This means we can use the same filter throughout our theme or plugin files, and can also add or remove the filters we don’t need. For example, if you normally disable emoji support (as I do on most new sites), then you can simply remove the call to add_filter( 'meta_content', 'convert_smilies' );.

** Updated on July 6th 2017 to correctly escape our field content before output using wp_kses_post. Thanks to Mark Wilkinson for suggesting this edit.

Reader Interactions


  1. Hi Craig,

    I do something similar here, however I notice you are not escaping or sanitising the output on the frontend.

    I think it would better for the output to be like this:

  2. Hey Craig, first of all this is a really great approach! Just one suggestion…it might be nice to add a few extra filters so that shortcodes and embeds get processed like they do with 'the_content' filter:

    $wp_embed = new \WP_Embed();

    add_filter( 'meta_content', 'wptexturize' );
    add_filter( 'meta_content', 'convert_smilies', 20 );
    add_filter( 'meta_content', 'convert_chars' );
    add_filter( 'meta_content', 'wpautop' );
    add_filter( 'meta_content', 'shortcode_unautop' );
    add_filter( 'meta_content', 'prepend_attachment' );
    add_filter( 'meta_content', 'do_shortcode', 11 );
    add_filter( 'meta_content', [ $wp_embed, 'run_shortcode' ], 8 );
    add_filter( 'meta_content', [ $wp_embed, 'autoembed' ], 8 );

Leave a Reply

Your email address will not be published. Required fields are marked *