Moving custom code from Rank Math or Yoast SEO

This page is for site builders and developers whose theme or plugins contain code written for Rank Math or Yoast SEO. Most Rank Math code keeps working without changes, because Anansi fires the same rank_math/… filters with the same arguments. Yoast SEO code does not: Anansi fires none of Yoast’s wpseo_* filters, so that code has to be moved to the anansi/… hooks. The page also covers reading meta, breadcrumb functions, and what Anansi deletes on uninstall.

Before you start

  1. Keep the old plugin active and leave Anansi in preview mode.
  2. Run wp anansi snapshot save before-switch to record what the site prints now.
  3. Import the data: wp anansi import rank-math (or yoast, aioseo, seopress, tsf, redirection). The import never changes the old plugin’s data.
  4. Check your custom code with wp anansi preview <url> and wp anansi snapshot compare before-switch --preview. On a preview request Anansi fires the Rank Math filters even while Rank Math is active, so you see what your Rank Math code will do after the switch.
  5. Deactivate the old plugin, then wp anansi mode live.

Code written for Rank Math

Filters that keep working

When Rank Math is not active, Anansi fires these Rank Math hooks with the same arguments, right after its own anansi/… hook. Most also run on preview requests. The full list, with the exact conditions, is in hooks.md.

Rank Math hookAnansi hookNotes
rank_math/frontend/titleanansi/title_raw
rank_math/frontend/descriptionanansi/description
rank_math/frontend/robotsanansi/robotsSame keyed array.
rank_math/frontend/advanced_robotsanansi/advanced_robots
rank_math/frontend/canonicalanansi/canonical
rank_math/frontend/prev_rel_link, …/next_rel_linkanansi/prev_rel_link, anansi/next_rel_link
rank_math/frontend/breadcrumb/itemsanansi/breadcrumb/itemsSame crumb format.
rank_math/frontend/breadcrumb/main_termanansi/breadcrumb/main_term
rank_math/json_ldanansi/json_ldCallbacks run inside Anansi’s graph at their own priority.
rank_math/schema/default_typeanansi/schema/default_type
rank_math/snippet/rich_snippet_article_entityanansi/schema/article_entity
rank_math/snippet/rich_snippet_{type}_entity and relatedanansi/snippet/…
rank_math/schema/validated_data, …/language, …/add_global_entitiesanansi/schema/…
rank_math/json_ld/breadcrumbs_enabled, …/disable_search, …/search_urlanansi/json_ld/…
rank_math/opengraph/{network}/{property} and the other rank_math/opengraph/… filtersanansi/opengraph/…
rank_math/sitemap/{x} (entries, index entries, exclusions, images, headers…)anansi/sitemap/{x}
rank_math/excluded_post_types, rank_math/excluded_taxonomiesanansi/excluded_post_types, anansi/excluded_taxonomies
rank_math/webmaster/{id}anansi/webmaster/{id}
rank_math/redirection/pre_search, …/get_clean_patternanansi/redirection/…Rank Math not active only.
rank_math/instant_indexing/publish_url, …/submit_urlanansi/indexnow/publish_url, anansi/indexnow/submit_urlsRank Math not active only.
rank_math/llms_txt/…anansi/llms_txt/…Rank Math not active only.
rank_math/frontend/rss/…, …/attachment/redirect_url, …/add_ugc_attribute, …/remove_reply_to_comanansi/frontend/…
rank_math/blocks/{block}/title_wrapper, rank_math/block/preserve_line_breaks, rank_math/schema/block/…anansi/…FAQ and HowTo blocks.
rank_math/head (action)—Fired after Anansi’s head block, so did_action( 'rank_math/head' ) checks still see an SEO plugin.

If a Rank Math hook is not in the full list, Anansi does not fire it. One example: rank_math/frontend/disable_adjacent_rel_links. Use anansi/disable_adjacent_rel_links instead.

Should you rename your hooks?

You do not have to. Moving to the anansi/… names is still a good idea when you touch the code anyway:

  • The anansi/… hook always runs when Anansi builds that output. A few Rank Math names do not run on preview requests (see the list above).
  • If Rank Math is reactivated later, Anansi steps back and stops firing the Rank Math names, so your code then runs only for Rank Math again.
  • Anansi-only hooks, such as anansi/meta/sources and anansi/head/tags, have no Rank Math version.

To run on both plugins during the move, hook both names with the same callback. Anansi never fires the Rank Math name while Rank Math prints the page, so the callback does not run twice for one output:

foreach ( array( 'rank_math/frontend/description', 'anansi/description' ) as $hook ) {
    add_filter( $hook, 'mytheme_seo_description' );
}

On a preview request (Rank Math still active), Anansi fires both names for its own output. If your callback is not safe to run twice on the same value, hook only one name.

Rank Math classes and functions

Anansi does not define Rank Math’s PHP classes, such as RankMath\Helper or RankMath\Paper\Paper. Code that calls them must check class_exists() first, or move to the Anansi equivalents:

Rank Math callAnansi replacement
RankMath\Helper::get_settings( 'titles.title_separator' )Anansi_Titles::get( 'title_separator' )
RankMath\Helper::get_settings( 'general.breadcrumbs' )Anansi_General::get( 'breadcrumbs' )
get_post_meta( $id, 'rank_math_title', true )Anansi_Meta::post( $id, 'title' )
get_post_meta( $id, 'rank_math_primary_category', true )Anansi_Meta::post( $id, 'primary_category' )
rank_math_the_breadcrumbs(), rank_math_get_breadcrumbs()Same functions, defined by Anansi (see below).
defined( 'RANK_MATH_VERSION' ) to decide whether to print SEO tagsfunction_exists( 'anansi_is_active' ) && anansi_is_active()

Code written for Yoast SEO

Anansi does not fire Yoast’s filters. Move each one to its Anansi hook. The arguments differ, so check each callback against hooks.md.

Yoast SEO hookAnansi hookWhat changes
wpseo_titleanansi/title_rawSame idea: a plain-text title.
wpseo_metadescanansi/description
wpseo_canonicalanansi/canonicalReturn '' for none (Yoast used false).
wpseo_robots, wpseo_robots_arrayanansi/robotsAnansi passes a keyed array ('index' => 'noindex'), not a string.
wpseo_opengraph_title, wpseo_opengraph_descanansi/opengraph/facebook/og_title, …/og_description
wpseo_opengraph_imageanansi/opengraph/facebook/image
wpseo_twitter_titleanansi/opengraph/twitter/twitter_title
wpseo_schema_graphanansi/json_ldAnansi’s nodes are keyed (publisher, WebPage, …); return the array with your nodes added.
wpseo_breadcrumb_linksanansi/breadcrumb/itemsCrumbs are array( 0 => label, 1 => url, 'hide_in_schema' => bool ), not text / url.
wpseo_sitemap_exclude_post_typeanansi/sitemap/exclude_post_type( bool $exclude, string $post_type ).
wpseo_sitemap_exclude_taxonomyanansi/sitemap/exclude_taxonomy( bool $exclude, string $taxonomy ).
wpseo_exclude_from_sitemap_by_post_idsanansi/sitemap/posts_to_excludeReceives the current list of IDs.
wpseo_sitemap_indexanansi/sitemap/indexRaw <sitemap> XML, as in Yoast.

Yoast template variables use %%title%%; Anansi uses %title%. The importer converts stored templates and per-post titles. Variables in your own code must be changed by hand. Port custom Yoast variables registered with wpseo_register_var_replacement() to anansi/vars/{name} filters (see hooks.md).

Yoast’s meta is not read through live. Anansi only reads its own keys and Rank Math’s. Run wp anansi import yoast to copy the values into _anansi_* keys, or, for plain-text fields such as the title and description, map single keys with anansi/meta/sources when the values hold no %%variables%%.

Reading SEO meta

Before the switch, code may read rank_math_* or _yoast_wpseo_* meta directly. After the switch, new edits are saved to _anansi_* keys, so direct reads of the old keys miss them. Read through Anansi instead:

function mytheme_seo_description( $post_id ) {
    if ( class_exists( 'Anansi_Meta' ) ) {
        return (string) Anansi_Meta::post( $post_id, 'description' );
    }
    return (string) get_post_meta( $post_id, 'rank_math_description', true );
}

Anansi_Meta::post() tries _anansi_description, then rank_math_description, then your anansi/meta/sources keys. See functions.md.

Meta key names match Rank Math’s after the prefix: rank_math_title → _anansi_title, rank_math_robots → _anansi_robots, rank_math_primary_category → _anansi_primary_category. The one exception is rank_math_news_sitemap_robots → _anansi_news_robots.

Themes that call the old plugin’s breadcrumb function keep working. When Anansi is in charge and the old plugin is gone, Anansi defines:

Old pluginFunctionShortcode
Rank Mathrank_math_the_breadcrumbs(), rank_math_get_breadcrumbs()[rank_math_breadcrumb]
Yoast SEOyoast_breadcrumb()[wpseo_breadcrumb]
All in One SEOaioseo_breadcrumbs()[aioseo_breadcrumbs]
SEOPressseopress_display_breadcrumbs()[seopress_breadcrumbs]

They print Rank Math’s markup (<nav class="rank-math-breadcrumb">). If your CSS targeted Yoast’s or AIOSEO’s markup, adjust it or rebuild the HTML with the anansi/breadcrumb/html filter. Keep your function_exists() checks: the functions exist only on front-end page requests while Anansi is in charge. Details in functions.md.

Redirects

While Rank Math’s redirect table is still there and not imported, Anansi reads it (read-only) and answers those redirects too. wp anansi redirects list --source=rank-math shows them. Importing copies them into Anansi’s own tables. Rank Math’s table is never changed.

Code that hooked rank_math/redirection/pre_search keeps working once Rank Math is inactive. Code that wrote into Rank Math’s tables directly must move to wp anansi redirects add or Anansi’s admin screen; Anansi’s table layout is internal.

Uninstall behaviour

Deactivating Anansi removes its scheduled video lookups and IndexNow sends, and makes WordPress rebuild rewrite rules on the next request. It deletes no data.

Deleting Anansi from the Plugins screen runs uninstall.php. On multisite it runs for every site. It deletes only Anansi’s own data:

WhatDeleted
Optionsanansi_settings, anansi_mode, anansi_titles, anansi_general, anansi_preview_key, anansi_previewed, anansi_video, anansi_sitemap, anansi_sitemap_cache_gen, anansi_blocks, anansi_crawlers, anansi_indexnow_log, anansi_indexnow_queue, anansi_links and its state options, anansi_abilities, anansi_google, anansi_google_secret, anansi_google_token, anansi_import_state, anansi_import_dry, anansi_redirects_* state options, anansi_tweaks_rewrite_state, and every anansi_snapshot_* option.
MetaEvery post, term and user meta key starting with _anansi_.
Tables{prefix}anansi_redirects, {prefix}anansi_redirects_index, {prefix}anansi_redirects_index_b, {prefix}anansi_404_log, {prefix}anansi_link_vectors.
TransientsAnansi’s caches (sitemaps, llms.txt, link suggestions, Google replies, redirect notices).
Cronanansi_video_fetch, anansi_indexnow_flush, anansi_redirects_daily, anansi_redirects_rebuild, anansi_links_index_tick, anansi_links_embed_tick.

Anansi never touches another plugin’s data, on uninstall or at any other time. That includes rank_math_* meta and options, Rank Math’s redirect table, _yoast_wpseo_* meta, wpseo* options, and the data of All in One SEO, SEOPress, The SEO Framework and Redirection. If you remove Anansi and reactivate the old plugin, the old plugin finds its data as it left it. Changes made in Anansi after the switch stay in Anansi’s keys and are deleted with it.

If you want to keep Anansi’s data, deactivate the plugin instead of deleting it.