Hooks and filters

Every public RankKit SEO action and filter, with its parameters and what it changes, plus PHP examples for head tags, schema, llms.txt and agent tools.

Updated 9 min read
On this page

RankKit SEO exposes WordPress actions and filters so you can change its output and extend it from a theme or a small plugin. All hooks start with speedrank_.

Put the code in a site-specific plugin or a child theme's functions.php, so it survives theme and plugin updates. Filters must return a value of the same type they receive.

Front-end output

speedrank_context

apply_filters( 'speedrank_context', array $ctx )

The resolved SEO values for the current request, used for the <title>, meta description, robots meta, canonical and social tags. Keys: kind, object, title, description, noindex, nofollow, canonical, image, og_title, og_description. It runs once per request and the result is reused.

// Noindex internal search-like pages that use a custom query var.
add_filter( 'speedrank_context', function ( $ctx ) {
	if ( get_query_var( 'filter' ) ) {
		$ctx['noindex'] = true;
	}
	return $ctx;
} );

speedrank_head_tags

apply_filters( 'speedrank_head_tags', array $tags, array $ctx )

The list of HTML tags RankKit SEO prints in <head> (meta description, canonical, verification codes, Open Graph and X tags), one string per tag. The output is passed through wp_kses, so only <meta> (with name, property, content) and <link> (with rel, href) survive.

add_filter( 'speedrank_head_tags', function ( $tags, $ctx ) {
	$tags[] = '<meta name="author" content="' . esc_attr( get_bloginfo( 'name' ) ) . '" />';
	return $tags;
}, 10, 2 );

speedrank_social_tags

apply_filters( 'speedrank_social_tags', array $tags, array $ctx )

Open Graph and X card values as property => content, for example og:title, og:image, twitter:card. Empty values are skipped when printing. Keys starting with twitter: are printed with name=, the rest with property=.

add_filter( 'speedrank_social_tags', function ( $tags, $ctx ) {
	$tags['twitter:creator'] = '@yourhandle';
	return $tags;
}, 10, 2 );

Schema

speedrank_schema_graph

apply_filters( 'speedrank_schema_graph', array $graph, array $ctx )

The full JSON-LD @graph array (Organization or Person, WebSite, WebPage, BreadcrumbList, Article and so on) before it is printed. Add, change or remove nodes.

// Remove the WebSite node's search action.
add_filter( 'speedrank_schema_graph', function ( $graph, $ctx ) {
	foreach ( $graph as &$node ) {
		if ( isset( $node['@type'] ) && 'WebSite' === $node['@type'] ) {
			unset( $node['potentialAction'] );
		}
	}
	return $graph;
}, 10, 2 );
Filter Parameters Use
speedrank_schema_items array $items, array $ctx, WP_Post|null $post The schema items for the current page (from the schema manager) before they are turned into nodes. RankKit SEO Pro adds schema template items here.
speedrank_schema_item_types array $types The schema types an editor can add to a post, keyed by type.
speedrank_schema_custom_field string $value, string $field, WP_Post|null $post The value of a %cf:field% variable in schema fields. Starts as an empty string; RankKit SEO Pro fills it from ACF, Meta Box, Pods, ACPT and post meta.
speedrank_post_videos array $videos, WP_Post $post Videos detected in a post, used for video schema and the video sitemap.
speedrank_product_schema array $node, WC_Product $product, string $url The WooCommerce Product schema node.
speedrank_product_brand string $brand, WC_Product $product The brand name used in Product schema.

speedrank_breadcrumbs

apply_filters( 'speedrank_breadcrumbs', array $items )

The breadcrumb trail as a list of array( 'label' => string, 'url' => string ). The last item (the current page) has an empty url. The trail feeds the [speedrank_breadcrumbs] shortcode, the speedrank_breadcrumbs() template tag and BreadcrumbList schema.

// Rename the first crumb.
add_filter( 'speedrank_breadcrumbs', function ( $items ) {
	if ( $items ) {
		$items[0]['label'] = 'Start';
	}
	return $items;
} );

See Shortcodes and template tags.

Title and description variables

speedrank_variables

apply_filters( 'speedrank_variables', array $map, WP_Post|WP_Term|null $object, string $template )

The %variable% => value map used to replace template variables in titles and descriptions. Variables left without a value are removed from the output.

speedrank_variable_catalog

apply_filters( 'speedrank_variable_catalog', array $vars )

The %variable% => description list shown in the settings UI. Add your variable here so editors can see it, and give it a value with speedrank_variables.

add_filter( 'speedrank_variable_catalog', function ( $vars ) {
	$vars['%brand%'] = 'Brand name';
	return $vars;
} );

add_filter( 'speedrank_variables', function ( $map, $object, $template ) {
	$map['%brand%'] = 'Acme';
	return $map;
}, 10, 3 );

Content analysis and AI

Filter Parameters Use
speedrank_builder_content string $html, WP_Post $post, string $builder The HTML RankKit SEO reads for a post (analysis, audit, AI). $builder is the detected page builder, or ''. Use it to supply content from a builder RankKit SEO can't read.
speedrank_analysis_content string $html, WP_Post $post The content used by the on-page SEO analyzer.
speedrank_ai_content string $html, WP_Post $post The post content sent to your AI provider. Tags and shortcodes are stripped and the text is trimmed after this filter.
// Keep a members-only section out of AI requests.
add_filter( 'speedrank_ai_content', function ( $html, $post ) {
	return preg_replace( '#<div class="members-only">.*?</div>#s', '', $html );
}, 10, 2 );

llms.txt

Filter Parameters Use
speedrank_llms_txt string $content The finished llms.txt document.
speedrank_llms_query_args array $args The get_posts() arguments used for each post type listed in llms.txt.
speedrank_llms_cache_key string $key The transient key llms.txt is cached under (used for per-language files).
speedrank_llms_cache_keys array $keys All cache keys to clear when llms.txt is rebuilt.
speedrank_llms_full_txt string $content The llms-full.txt document (RankKit SEO Pro).

llms.txt is cached for 12 hours, so changes from these filters show up when the cache expires. To see them at once, ask an agent to run regenerate_llms_txt, which rebuilds the file.

add_filter( 'speedrank_llms_txt', function ( $content ) {
	return $content . "\n## Contact\n\n- [Support](https://example.com/support)\n";
} );

Sitemaps

speedrank_sitemap_index_entries

apply_filters( 'speedrank_sitemap_index_entries', array $entries )

Extra entries for the sitemap index. Each entry is an array with loc (required) and optionally lastmod.

add_filter( 'speedrank_sitemap_index_entries', function ( $entries ) {
	$entries[] = array( 'loc' => home_url( '/shop-sitemap.xml' ) );
	return $entries;
} );

Local SEO

Filter Parameters Use
speedrank_local_business array|null $business, string $location The business data for a location ('' is the site's main business).
speedrank_local_location_choices array $choices Locations offered in the Business info block and shortcode (value, label).
speedrank_local_has_locations bool $has Whether extra locations exist (turns on the KML file even without a main business).
speedrank_local_store_list bool $enabled Whether the store list is available in the block editor.
speedrank_kml_locations array $list The businesses listed in locations.kml.

RankKit SEO Pro uses these filters for multiple locations.

Multilingual

Filter Parameters Use
speedrank_multilingual_provider string $provider Override the detected multilingual plugin: polylang, wpml, translatepress or ''.
speedrank_multilingual_languages array $languages, string $provider The site's languages as RankKit SEO sees them.
speedrank_print_hreflang bool $print, string $provider Whether RankKit SEO prints hreflang links. By default it does only when the multilingual plugin doesn't.

Email reports

Filter Parameters Use
speedrank_report_recipients array $emails Who gets the report. Default: the site admin email.
speedrank_report_data array $data The numbers in the report.

The report schedule and branding are set in RankKit SEO Pro's report settings. See Email reports.

add_filter( 'speedrank_report_recipients', function ( $emails ) {
	$emails[] = 'seo@example.com';
	return $emails;
} );

AI agent tools

speedrank_abilities

apply_filters( 'speedrank_abilities', array $definitions )

Every agent tool, keyed by tool name. The list feeds the MCP server and the WordPress Abilities API. Each definition is an array with:

Key Required Meaning
title Yes Short label.
description Yes What the tool does, written for an AI agent.
area Yes Token permission area: content, redirects, audit, analytics, ai, settings or history.
write Yes true for tools that change something. Write tools get dry_run and reason inputs automatically.
cap Yes The WordPress capability needed. edit_posts or manage_options are mapped to the matching RankKit SEO role-manager permission for the area.
run Yes Callable that receives the arguments array and returns an array or a WP_Error.
input No JSON Schema properties for the arguments.
required No List of required argument names.
also No A second area the token needs, for example array( 'ai' => 'write' ).
destructive No Marks the tool as destructive in its annotations.
group No The group it is listed under in wp-admin: site, indexing, content, media, ai, audit, redirects, history or analytics.
add_filter( 'speedrank_abilities', function ( $defs ) {
	$defs['count_drafts'] = array(
		'title'       => 'Count draft posts',
		'description' => 'How many posts are saved as drafts.',
		'area'        => 'content',
		'write'       => false,
		'cap'         => 'edit_posts',
		'run'         => static function ( array $args ) {
			return array( 'drafts' => (int) wp_count_posts()->draft );
		},
	);
	return $defs;
} );

For a write tool, save changes through RankKit SEO's write path so they are logged, previewed with dry_run and held for approval like built-in tools: pass \SpeedRank\Agents\Abilities::write_context( $args ) as the context of \SpeedRank\Core\SeoData::update().

Change Log object types

These filters let an integration register its own object type, so changes to it go through the Change Log with approval, dry runs and revert.

Filter Parameters Use
speedrank_object_types array $types Add your object type names.
speedrank_read_raw mixed $value, string $type, int $id, string $field Return the current value of a field of your type.
speedrank_write_raw mixed $old, string $type, int $id, string $field, mixed $value Write the value. Return the previous value, true if the value read before is already right, or a WP_Error.
speedrank_validate_field mixed $value, string $type, string $field Validate and normalise a value before it is compared and saved. Return a WP_Error to refuse it.
speedrank_check_object true|WP_Error $ok, string $type, int $id Return a WP_Error if the object doesn't exist.
speedrank_object_label string $label, string $type, int $id The label shown for the object in the Change Log.

Other filters

Filter Parameters Use
speedrank_admin_integrations array $integrations Extra integration data passed to the RankKit SEO admin app. Used internally by the Local SEO, WooCommerce and multilingual integrations.
speedrank_is_pro bool $is_pro RankKit SEO Pro only: override the license check result. Has no effect in the free plugin.

Actions

Action Parameters Fires
speedrank_data_written string $type, int $id, string $field, mixed $value, mixed $old After RankKit SEO writes a value through its own write path: settings, SEO fields, alt text, redirects and registered object types, including approved changes and reverts. SEO meta saved directly through the WordPress REST API (as the block editor does) is logged in the Change Log but doesn't fire this action.
speedrank_audit_completed array $result After a site audit run. $result holds the score, grade, categories and issues.
speedrank_backup_restored array $data, array $parts After a backup is restored.
speedrank_fs_loaded none When the RankKit SEO plugin file has loaded, after the Freemius SDK is set up.
speedrank_daily none Once a day (WP-Cron). RankKit SEO uses it for housekeeping: purging old Change Log entries, removing expired tokens and pruning logs.
// Notify a webhook when an SEO title changes.
add_action( 'speedrank_data_written', function ( $type, $id, $field, $value, $old ) {
	if ( 'post' === $type && 'title' === $field ) {
		wp_remote_post( 'https://hooks.example.com/seo', array(
			'body' => wp_json_encode( array( 'post' => $id, 'old' => $old, 'new' => $value ) ),
		) );
	}
}, 10, 5 );

// Alert when the audit score drops below 70.
add_action( 'speedrank_audit_completed', function ( $result ) {
	if ( isset( $result['score'] ) && $result['score'] < 70 ) {
		wp_mail( get_option( 'admin_email' ), 'SEO score dropped', 'Score: ' . $result['score'] );
	}
} );

FAQ

Is there a filter for the SEO title?

Use speedrank_context and change $ctx['title'], which RankKit SEO uses for the <title> tag on the front end. To change the Open Graph and X title too, change $ctx['og_title'] or use speedrank_social_tags.

Can I filter what the AI and the analyzer read?

Yes. speedrank_builder_content changes the content every feature reads, speedrank_analysis_content only what the analyzer reads, and speedrank_ai_content only what is sent to your AI provider.

Are there WP-CLI commands?

No. RankKit SEO doesn't register WP-CLI commands.

Was this page helpful?

Still need help?

Email us with your WordPress and RankKit SEO versions and what you tried. Pro customers get priority replies.

Contact support