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).
Breadcrumbs
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.