Skip to content

Extending with hooks

SleekRank fires filters and actions that let site code change the data a page is built from and the HTML it produces, and add its own data source types, mapping types and sitemap integrations. This page shows how they fit together; Hooks reference lists every public hook with its parameters, generated from the code.

Changing the data

sleekRank/data/item filters the row a generated page is built from, after it was found in the cache and before any mapping reads it. sleekRank/data/item/{slug} then does the same for one page group, named by its slug. Both run for public pages and the workspace preview. On a public page they run while WordPress parses the request, before the main query, so conditional tags such as is_page() do not answer in them yet.

PHP
add_filter("sleekRank/data/item", function ($item, $pageGroup) {
    $item["name"] = strtoupper($item["name"]);
    return $item;
}, 10, 2);

add_filter("sleekRank/data/item/city-pages", function ($item) {
    $item["description"] = wp_trim_words($item["description"], 30);
    return $item;
});

sleekRank/data/resolved fires once the row is final, on template_redirect before the base page loads, with the row and the page group.

Changing mapping values

Every value a tag, selector or meta mapping writes passes through sleekRank/replacement/value, then through sleekRank/replacement/value/{type} for its mapping type (tag, selector or meta). The value is already escaped for where it goes. List mappings do not pass through these filters.

PHP
add_filter("sleekRank/replacement/value/meta", function ($value, $mapping, $data) {
    return $mapping["target"] === "description"
        ? wp_trim_words($value, 25)
        : $value;
}, 10, 3);

Changing the page

Four filters receive the page’s complete HTML:

  • sleekRank/output/before and sleekRank/output/after run on every generated page and preview, before and after the mappings, with the page group and the row
  • sleekRank/replacements/before and sleekRank/replacements/after run directly around the mappings, with the row and the mappings, and only when the group has at least one mapping
PHP
add_filter("sleekRank/output/after", function ($html, $pageGroup, $data) {
    $banner = '<div class="generated-page-banner">' . esc_html($data["name"] ?? "") . "</div>";
    return preg_replace("/<body([^>]*)>/", '<body$1>' . $banner, $html, 1);
}, 10, 3);

On a public page, Rank points the canonical link and og:url at the generated URL after these filters, whichever of WordPress, Yoast SEO, Rank Math, The SEO Framework or All in One SEO printed them. sleekRank/output/canonical filters that URL; return an empty string to keep the base page’s canonical:

PHP
add_filter("sleekRank/output/canonical", function ($url, $pageGroup) {
    return "city-pages" === $pageGroup->getSlug() ? "" : $url;
}, 10, 2);

sleek_rank_related_items() lists a page’s siblings with a title taken from the first of pageTitle, heroHeadline, title and name the row has, or its slug; sleekRank/data/relatedItem filters each listed item with its row, so the title can come from any field.

The registration hooks below fire on after_setup_theme, so a plugin or the theme’s functions.php can add to them.

Adding a data source type

sleekRank/register/dataSources passes the data source registry after the seven built-in types are registered. Register a class that implements SleekRank\DataSourceInterface; extending SleekRank\Sources\BaseDataSource and implementing its fetchRaw() gives the new type Rank’s cache, refresh and lookups. The class receives the source’s config array, with cacheDuration added.

PHP
add_action("sleekRank/register/dataSources", function ($registry) {
    $registry->register("airtable", MyAirtableDataSource::class);
});

sleekRank/dataSource/registered fires for every registered type. The workspace editor offers the built-in types for new sources and keeps a source of a custom type as it is, showing its type; its settings are configured through WP-CLI or REST (see Data sources). A mapping of a custom type is kept and shown the same way.

Adding a mapping type

sleekRank/register/replacements passes the replacement engine after the four built-in mapping types are registered. Register an object that implements SleekRank\ReplacementInterface: its supports() decides which mappings it handles, and replace() returns the changed HTML.

PHP
add_action("sleekRank/register/replacements", function ($engine) {
    $engine->registerReplacement(new MyCountdownReplacement());
});

Adding a sitemap integration

sleekRank/register/sitemapIntegrations passes the sitemap registry after the built-in SEO plugin integrations and before the WordPress core fallback. Register an object that implements SleekRank\SitemapIntegrationInterface; the first registered integration whose isActive() is true is used. Build it on sleekRank()->getSitemapProvider(), which supplies the entries.

PHP
add_action("sleekRank/register/sitemapIntegrations", function ($registry) {
    $registry->register(
        new MySitemapIntegration(sleekRank()->getSitemapProvider())
    );
});

sleekRank/sitemap/urlsPerSitemap changes how many URLs one sitemap file holds (see Sitemap).

Lifecycle and build hooks

  • sleekRank/init fires once Rank has booted, on after_setup_theme, with the instance sleekRank() returns
  • sleekRank/rewrites/registered fires after the published groups’ rewrite rules are added
  • sleekRank/activated and sleekRank/deactivated fire when Rank is activated or deactivated on a site
  • sleekRank/runtime/allowRouteInventory decides whether sleek_rank_generated_route_inventory() may list the generated URLs in a request other than WP-CLI, where wp sleek rank routes uses it

Stay in the Loop!  

Be the first to hear about new updates, special offers, and helpful tips, delivered straight to your inbox.

We respect your inbox (and your privacy). Read our privacy policy.