Skip to content
Subset

For developers

Developer reference

Template variables, the filters on every tag, adding schema pieces and sitemaps, breadcrumbs, the meta keys, REST and WP-CLI.

Every tag SEO prints, every template variable, schema piece, sitemap entry and content check has a filter. Hooks receive a Subset\SEO\Templates\Subject: what the page is about. Build one yourself with Subject::current() for the main query or Subject::for_post( $post ).

Titles and descriptions

Titles and descriptions come from templates, set per page type in Settings → SEO → Titles & meta. A post’s own SEO title or description replaces the template’s.

<?php
// A %%price%% variable for templates. Return "" when it doesn't apply.
add_filter( 'subset_seo_template_variables', function ( array $resolvers ): array {
	$resolvers['price'] = fn ( \Subset\SEO\Templates\Subject $subject ): string =>
		$subject->post() ? (string) get_post_meta( $subject->post()->ID, 'price', true ) : '';
	return $resolvers;
} );

// The rendered title, as plain text. Return "" to leave WordPress's own.
add_filter( 'subset_seo_title', function ( string $title, $subject ): string {
	return $title;
}, 10, 2 );

subset_seo_description works the same way for the meta description. Social titles and descriptions fall back to both.

Head tags

<?php
// The canonical URL, or "" for none. og:url and the schema's page @id follow it.
add_filter( 'subset_seo_canonical', function ( string $url, $subject ): string {
	return $url;
}, 10, 2 );

// Robots directives, before core prints them through wp_robots.
add_filter( 'subset_seo_robots', function ( array $robots, $subject ): array {
	$robots['max-image-preview'] = 'large';
	return $robots;
}, 10, 2 );

subset_seo_open_graph and subset_seo_twitter filter the social tags, and subset_seo_social_image picks the share image. To print tags of your own inside SEO’s head block, use the subset_seo_head action.

Schema

The graph is one JSON-LD @graph per page. Each node is a piece that points at the others by @id. Built-in pieces are website, organization, person, webpage, primaryimage, article, author and breadcrumb.

<?php
// Change one piece's data. Return an empty array to drop it.
add_filter( 'subset_seo_schema_piece_article', function ( array $data, $context ): array {
	$data['inLanguage'] = 'en-GB';
	return $data;
}, 10, 2 );

To describe something new, add a class implementing Subset\SEO\Schema\Piece (key(), needed( Context ) and data( Context )) through subset_seo_schema_pieces. subset_seo_schema_graph filters the whole graph before it prints.

Sitemaps

The index is /sitemap.xml, and each provider’s files are /{name}-sitemap.xml, /{name}-sitemap2.xml and so on. Files are cached and rebuilt when content changes.

<?php
// Leave a post, term or user out. Noindexed objects are left out already.
add_filter( 'subset_seo_sitemap_exclude', function ( bool $excluded, string $kind, $object ): bool {
	return $excluded || ( 'post' === $kind && get_post_meta( $object->ID, '_hide', true ) );
}, 10, 3 );

Add a provider of your own, a Subset\SEO\Sitemaps\Provider, through subset_seo_sitemap_types. subset_seo_sitemap_entry filters one URL and subset_seo_sitemap_per_file sets how many go in each file (1,000 by default).

Show the trail with the subset-seo/breadcrumbs block, the [subset_seo_breadcrumbs] shortcode or the template function:

<?php
// In a classic theme, declare support so the page's schema includes the BreadcrumbList.
add_theme_support( 'subset-seo-breadcrumbs' );

subset_seo_breadcrumbs( array( 'separator' => '/' ) );

subset_seo_breadcrumb_links filters the trail, from the home page to the current page.

Content checks

The editor’s checks run in the browser. Add one from a script that depends on subset-seo-editor:

subsetSEO.analysis.register({
  id: "acme_price",
  group: "seo", // or "readability"
  run: (paper) =>
    paper.text.includes("$")
      ? { status: "good", message: "The price is mentioned." }
      : { status: "note", message: "The text doesn't mention a price." },
});

A check returns good, note or problem, or null to skip. Its settings come from subset_seo_analysis_checks on the PHP side.

Meta keys

Values are stored under _subset_seo_ plus the field name: title, description, canonical, robots, og_title, og_description, og_image, tw_title, tw_description, tw_image, tw_card, focus_keyphrase, schema_type, breadcrumb_title and primary_term_{taxonomy}. Write them through the REST API or WP-CLI rather than directly, so values are cleaned the way the editor cleans them.

Uninstalling keeps these values, so another SEO plugin can import them. Settings → SEO → Tools → Remove all Subset SEO data deletes them.

REST API and WP-CLI

The REST namespace is subset-seo/v1, with routes for an object’s SEO values (/meta/{type}/{id}), the search preview, imports and flushing the sitemap cache.

wp subset seo check 42                                   # rendered title, description, robots, checks
wp subset seo meta set post 42 description "A new description"
wp subset seo import yoast --dry-run                     # preview an import
wp subset seo sitemap flush
wp subset seo settings export settings.json

Extending the plugin

An add-on attaches on subset_seo_loading, which fires before any component registers. subset_seo_admin_tabs adds a tab to Settings → SEO, printed on subset_seo_admin_tab_{slug}, and subset_seo_settings_defaults adds settings.