Advanced Custom Fields + Emojis

The challenge: Figure out why Advanced Custom Fields in wordpress didn't save emojis.
The stakeholder: My fun SEO coworker who wants to shove emojis into ld+json for the chance at ranking higher in google search results.

This was a fun problem to work on. I've had an growing interest in SEO for a while now. While I prefer generating ld+json on the component level when I can, sometimes the SEO's want a lot more control. How much control they get is contingent on the tools we provide for them. I this case it was a simple textarea ACF field.

The problem?: ACF fields don't currently handle special characters very well -- that goes for things like ™ or 🤡.

The approach: My search led me to two paths. The first path was changing the formatting rules of the entire database. This is a site with a long history and hundreds of posts. Not gonna take that risk just to shove a fire extinguisher emoji into some ld+json. The other option is to take the data before it's saved, encode it into a format that will retain the emoji, then decode it once again when we need to get that data back (so the clown looks like a clown and not a bunch of garble).

The solution: In a nutshell, we need to accomplish 3 things:

  1. Encode before ACF saves 
  2. Decode before ACF fetches that data for viewing in the admin panel (so my SEO's don't have a heart attack)
  3. Decode before ACF fetches that data for the final output on the page 

 1) Encode before ACF Saves
add_action('acf/save_post', 'encode_emoji_schema');
function encode_emoji_schema( $post_id ) {
$schema_field = get_field_object('page_schema', $post_id)['key'];
// Check if a specific value was updated
if( isset($_POST['acf'][$schema_field] ) {
$_POST['acf'][$schema_field] = urlencode( $_POST['acf'][$schema_field] );
}
};

Breakdown: 
  • add_action(); // interrupt WP render to do a thing
  • acf/save_post; // ACF specific hook, fires when saving ACF
  • get_field_object(); // ACF function
  • $_POST; superglobal PHP array of variables being POSTed
  • urlencode(); // replaces all non-alphanumeric chars with encoded junk


2) Decode for the Admin Output
add_filter('acf/prepare_field/name=page_schema', 'admin_emoji_decode', 5);
function admin_emoji_decode( $field ) {
$field['value'] = stripslashes( urldecode( $field['value'] ) );
return $field;
}

Breakdown:
  • add_filter(); // alter existing data
  • acf/prepare_field/name=page_schema // Alter data prior to rendering within a form (cms)
  • $field;
  • stripslashes(); // remove quotes from
  • urldecode(); // reverse encoding


3) Decode for the Page Output
add_filter('acf/load_value/name=page_schema', 'render_emoji_decode', 5);
function render_emoji_decode( $value ) {
$value = stripslashes( urldecode( $value ) );
return $value;
}

Breakdown:
  • acf/load_value/name=page_schema // Alter data for rendering
  • $value

Comments