The SEO Framework · KB

★︎ Start with TSF
  • Extensions
  • Documentation
  • Pricing
  1. Home
  2. Knowledge Base
  3. API
  4. Filter reference for The SEO Framework · KB

Filter reference for The SEO Framework — Contents

  • Query filters
  • Title filters
  • Description filters
  • Robots filters
  • Image filters
  • Sitemap filters
  • List edit settings filters
  • Post SEO settings filters
  • SEO Bar filters

Filter reference for The SEO Framework

Published on June 9, 2022
Revised on January 28, 2025

Filters allow you to change interpreted data conditionally.

We recommend against using filters if you aren’t an avid PHP developer. This is because you must revalidate (and possibly update) your implementation on every major release, although that shouldn’t happen often.

As of v5.1.0, The SEO Framework registers over 170 filters.

Below you’ll find frequently requested filter implementations. Most examples below only work on TSF v5.0.0 or higher. It’s not an exhaustive list, because many filters now have options and only exist for backward compatibility reasons. Advanced filters, such as those used for script loading, aren’t listed here either. For these, we urge you to review the code.

If you don’t know how filters work or where to place them, read our filter guide first.

Query related

The query-related filters affect how The SEO Framework interacts with the interface.

Disable SEO support

N.B. This example filter does not affect the admin interface.

add_filter(
	'the_seo_framework_query_supports_seo',
	function ( $supported ) {

		$tsf = tsf();

		// This TSF method also works in the admin area, and prevents ID collision with terms.
		if ( $tsf->query()->is_singular() ) {

			// Define your excluded page IDs here.
			$excluded_ids = [ 42, 9001 ];

			// This TSF method can more accurately get the request ID than the standard API.
			$current_id = $tsf->query()->get_the_real_id();

			if ( in_array( $current_id, $excluded_ids, true ) ) {
				$supported = false;
			}
		}

		return $supported;
	},
);

Disable meta output

This filter hides all Open Graph and Facebook generation and output for a specific post ID on the front-end.

add_filter(
	'the_seo_framework_meta_generator_pools',
	/**
	 * @param string[] $generator_pools A list of tag pools requested for the current query.
	 *                                  The tag pool names correspond directly to their classes.
	 *                                  Do not register new pools; it'll cause a fatal error.
	 * @return string[] The adjusted pools.
	 */
	function ( $generator_pools ) {

		$tsfquery = tsf()->query();

		if ( $tsfquery->is_singular() && 42 === $tsfquery->get_the_real_id() ) {
			// Remove the Open Graph and Facebook meta tags from the page.
			// Known generators of TSF v5.1: 'Robots', 'Advanced_Query_Protection', 'URI',
			// 'Description', 'Theme_Color', 'Open_Graph', 'Facebook', 'Twitter', 'Webmasters',
			// and 'Schema'.
			$generator_pools = array_diff( $generator_pools, [ 'Open_Graph', 'Facebook' ] );
		}

		return $generator_pools;
	},
);

Title related

The title-related filters affect all functions that make use of the titles. This includes (and is not limited to) the meta title, generated descriptions, social metadata, and structured data (Schema.org).

Run shortcodes in the custom title.

N.B. This example filter is for custom titles, not generated titles. You can use them interchangeably.

add_filter(
	'the_seo_framework_title_from_custom_field',
	function ( $title, $args ) {
		return apply_shortcodes( $title );
	},
	10,
	2,
);

Set generated title prefix

Set an “Antique: ” title-prefix for all WooCommerce products.

Please note that the title input fields will not consider this filter’s output well, but the front-end will. It’s tricky considering moving parts, such as updating a title in the Block Editor.

N.B. This example filter is for generated titles, not custom titles. You can use them interchangeably.

add_filter(
	'the_seo_framework_title_from_generation',
	function ( $title, $args ) {

		$tsf = tsf();

		if ( null === $args ) {
			// We're in the loop.
			if (
				   $tsf->query()->is_singular()
				&& 'product' === $tsf->query()->get_current_post_type()
			) {
				$title_prefix = 'Antique: ';
			}
		} else {
			// We're on an admin page or generating a breadcrumb.
			if (
				   'single' === The_SEO_Framework\get_query_type_from_args( $args )
				&& 'product' === $tsf->query()->get_post_type_real_id( $args['id'] )
			) {
				$title_prefix = 'Antique: ';
			}
		}

		if ( isset( $title_prefix ) ) {
			// Sanitizing isn't necessary. TSF will do that for you.
			$title = "$title_prefix $title";
		}

		return $title;
	},
	10,
	2,
);

Remove title branding on all WooCommerce product categories.

N.B. The use of this filter is not recommended because search engines tend to ignore unbranded titles.

add_filter(
	'the_seo_framework_use_title_branding',
	function ( $use, $args ) {
		// Get taxonomy with admin support.
		$taxonomy = null === $args
			? tsf()->query()->get_current_taxonomy()
			: $args['taxonomy'];

		// If taxonomy is a WooCommerce product category, disable the branding.
		if ( 'product_cat' === $taxonomy ) {
			$use = false;
		}

		return $use;
	},
	10,
	2,
);

Description related

The description-related filters affect all functions that make use of the description. This includes (and is not limited to) the meta description, social metadata, and structured data (Schema.org).

Run shortcodes in the custom description.

add_filter(
	'the_seo_framework_custom_field_description',
	function ( $description, $args ) {
		return apply_shortcodes( $description );
	},
	10,
	2,
);

Use long descriptions instead of short descriptions for WooCommerce products

add_filter(
	'the_seo_framework_description_excerpt',
	function ( $excerpt, $args ) {

		$tsf       = tsf();
		$tsf_query = $tsf->query();

		if ( null === $args ) {
			// In the loop.
			$is_product = $tsf_query->is_product();
		} else {
			// Out the loop, admin etc.
			if ( 'single' === The_SEO_Framework\get_query_type_from_args( $args ) ) {
				$is_product = $tsf_query->is_product( $args['id'] );
			}
		}

		if ( $is_product ?? false ) {
			$product    = get_post( $args['id'] ?? $tsf_query->get_the_real_id() );
			$product_id = $product->ID;
			$tsf_post   = $tsf->data()->post();

			// Don't leak protected content.
			if ( $tsf_post->is_protected( $product_id ) )
				return $excerpt;

			$old_excerpt = $excerpt;
			// Don't get the excerpt from a non-HTML page builders. This cannot be deciphered early.
			$excerpt = $tsf_post->uses_non_html_page_builder( $product_id )
				? ''
				: $tsf_post->get_content( $product );

			if ( $excerpt ) {
				$tsf_html = $tsf->format()->html();
				// Apply the first half of TSF's description AI here: selectively strip content and HTML.
				$excerpt = $tsf_html->strip_paragraph_urls( $tsf_html->strip_newline_urls( $excerpt ) );
				$excerpt = $tsf_html->extract_content( $excerpt );
			}

			// Fall back to old excerpt if the new one has nothing useful.
			$excerpt = $excerpt ?: $old_excerpt;
		}

		return $excerpt;
	},
	10,
	2,
);

Robots related

The robots-related filters can be used to direct crawlers, like Googlebot.

Set noindex and nofollow for all post tags

add_filter(
	'the_seo_framework_robots_meta_array',
	function ( $meta, $args, $options ) {

		// Get taxonomy with admin support.
		$taxonomy = null === $args
			? tsf()->query()->get_current_taxonomy()
			: $args['taxonomy'];

		// If taxonomy is a Post Tag, disable indexing and link following.
		if ( 'post_tag' === $taxonomy ) {
			$meta['noindex']  = 'noindex';
			$meta['nofollow'] = 'nofollow';
		}

		return $meta;
	},
	10,
	3,
);

Add robots.txt rules

N.B. The SEO Framework overwrites the dynamic file to prevent plugin conflicts. So, you should always set your callback priority to a greater value than 10.

// This is a WordPress Core filter.
add_filter(
	'robots_txt',
	function ( $robots ) {

		$robots .= "\nDisallow: /my-custom-folder/\n";

		return $robots;
	},
	11,
);

The SEO Framework 5.1.0 also comes with a more advanced filter, called the_seo_framework_robots_txt_sections.

Image related

The image-related filters affect social metadata as well as structured data.

Append image generators for social images

This filter is advanced and powerful. For real-world usage, see this issue comment and this issue comment.

add_filter(
	'the_seo_framework_image_generation_params',
	function ( $params, $args, $context ) {

		// Let's not mess with non-social sharing images.
		if ( 'social' !== $context ) return $params;

		if ( null === $args ) {
			// In the loop.
			if ( is_singular() ) {
				// Append. Use array_unshift() on 'cbs' to prepend.
				$params['cbs']['custom'] = 'my_tsf_custom_singular_image_generator';
			}
		} else {
			// Out the loop. Use $args to evaluate the query...
			if ( 'single' === The_SEO_Framework\get_query_type_from_args( $args ) ) {
				// Singular.

				// Append. Use array_unshift() on 'cbs' to prepend.
				$params['cbs']['custom'] = 'my_tsf_custom_singular_image_generator';
			}
		}

		return $params;
	},
	10,
	3,
);

function my_tsf_custom_singular_image_generator( $args = null, $size = 'full' ) {

	// Arbitrary URL and ID.
	$url = 'https://example.com/path/to/image/';
	$id  = 42;

	if ( $url ) {
		yield [
			'url' => $url,
			'id'  => $id, // Optional. Used for alt-tag fetching and dimension testing.
		];
	}
}

Sitemap related

The sitemap is sufficient for all websites as-is. The sitemap doesn’t need to have all URLs of your website listed.

“Improving” the sitemap is utterly redundant… but, go ahead.

Add categories and tags to base sitemap

add_filter(
	'the_seo_framework_sitemap_additional_urls',
	function ( $custom_urls ) {

		// Set the taxonomy types you'd like to include.
		$taxonomies = [
			'category',
			'post_tag',
		];

		$tsf = tsf();

		// Sitemaps can loop over thousands of items. Run as little as possible in the loop: cache objects.
		$tsf_taxonomy      = $tsf->taxonomy();
		$tsf_sitemap_utils = $tsf->sitemap()->utils();
		$tsf_uri           = $tsf->uri();

		foreach ( $taxonomies as $tax ) {
			// When the taxonomy is disabled or isn't public, don't include it.
			if ( ! $tsf_taxonomy->is_supported( $tax ) ) continue;

			$terms = get_terms( [
				'taxonomy'   => $tax,
				'hide_empty' => true,
			] );

			if ( is_wp_error( $terms ) ) continue;

			foreach ( $terms as $term ) {
				if ( ! $tsf_sitemap_utils->is_term_included_in_sitemap( $term->term_id, $term->taxonomy ) )
					continue;

				$url = $tsf_uri->get_term_url( $term->term_id, $term->taxonomy );

				$custom_urls[ $url ] = [
					'lastmod' => null, // difficult to determine accurately.
				];
			}
		}

		return $custom_urls;
	},
);

List edit settings related

These filters are applicable to the post and term overview pages.

Hide quick-and bulk-edit

add_action(
	'the_seo_framework_after_admin_init',
	function () {
		// Hide quick and bulk-edit.
		remove_action( 'admin_init', [ The_SEO_Framework\Admin\Settings\ListEdit::class, 'init_quick_and_bulk_edit' ] );
		// Hide custom post states.
		remove_filter( 'display_post_states', [ The_SEO_Framework\Admin\Lists\PostStates::class, 'add_post_state' ] );
	},
);

Post SEO settings related

The post SEO settings are placed in a meta box on each public post type edit screen.

Change meta box priority

N.B. Only new users are affected by this filter. Users can drag and position the meta box to their liking, the location is stored and locked as a user-setting.

add_filter(
	'the_seo_framework_metabox_priority',
	function () {
		return 'default'; // Accepts 'high', 'default', 'low'. Default is 'high'.
	},
);

Move meta box to the sidebar

N.B. Only new users are affected by this filter. Users can drag and position the meta box to their liking, the location is stored and locked as a user-setting.

add_filter(
	'the_seo_framework_metabox_context',
	function () {
		return 'side'; // Accepts 'normal', 'side', and 'advanced'. Default is 'normal'.
	},
);

SEO Bar related

The SEO Bar helps you see what needs attention for each page. Since TSF v4.0, we provide an API. These are actions, not filters, but you’re probably reading this page because you want to adjust things — to which filters make more sense.

Register custom SEO Bar item

add_action(
	'the_seo_framework_seo_bar',
	function ( $interpreter, $builder ) {
		/**
		 * This is a collector method. However, it's best to use
		 * `register_seo_bar_item()` and `edit_seo_bar_item()` instead.
		 */
		$items = $interpreter::collect_seo_bar_items();

		// Don't do anything if there's a blocking redirect.
		if ( ! empty( $items['redirect']['meta']['blocking'] ) ) return;

		// Add a custom item:
		$interpreter::register_seo_bar_item(
			'something',
			[
				'symbol' => 'S',
				'title'  => __( 'Some assessment', 'my-text-domain' ),
				'status' => $interpreter::STATE_BAD,
				'reason' => __( 'Something bad happened.', 'my-text-domain' ),
				'assess' => [
					'something' => __( 'Something is not right.', 'my-text-domain' ),
					'else'      => __( 'Something else is not right either.', 'my-text-domain' ),
				],
			]
		);
	},
	10,
	2,
);

Adjust SEO Bar item

add_action(
	'the_seo_framework_seo_bar',
	function ( $interpreter, $builder ) {
		/**
		* This is a collector method. However, it's best to use
		* `register_seo_bar_item()` and `edit_seo_bar_item()` instead.
		*/
		$items = $interpreter::collect_seo_bar_items();

		// Don't do anything if there's a blocking redirect.
		if ( ! empty( $items['redirect']['meta']['blocking'] ) ) return;

		// Edit known items. Warning: Advanced magic! Know your PHP.
		// NB: If the item isn't registered, this won't produce errors, but all changes will be voided.
		$index_item                     = &$interpreter::edit_seo_bar_item( 'indexing' );
		$index_item['status']           = $interpreter::STATE_UNKNOWN;
		$index_item['reason']           = __( 'Robots.txt blocks all crawlers.', 'my-text-domain' );
		$index_item['assess']           = []; // clear all assessments... be considerate!
		$index_item['assess']['plugin'] = __( 'This is a developer site. Plugin "MyNoRobots - Robots.txt Robot Blocker" is activated.', 'my-text-domain' );
	},
	10,
	2,
);
Filed Under: API, The SEO Framework

Other articles

  • API

    • Breadcrumb shortcode
    • Constant reference for The SEO Framework
    • Using filters
  • The SEO Framework

    • Robots.txt blocks
    • Common plugin update issues
    • Headless mode
    • All you must know about sitemaps
    • Data stored in your database

Commercial

The SEO Framework
Trademark of CyberWire B.V.
Leidse Schouw 2
2408 AE Alphen a/d Rijn
The Netherlands
KvK: 83230076
BTW/VAT: NL862781322B01

Twitter  GitHub

Professional

Pricing
About
Support
Press

Rational

Blog
Privacy Policy
Terms and Conditions
Refund Policy

Practical

Documentation
TSF on WordPress
TSF on GitHub
TSFEM on here
TSFEM on GitHub
Feature Highlights

Fixing a bug in 2025 › The SEO Framework