WP Manifestindependent plugin directory
manifest / seo / prc-schema-seo

PRC Schema - SEO

Provides schema generation, SEO meta tags, primary term management, preview panels, and site-level template defaults for titles & descriptions for PRC Platform sites.

by Seth Rubenstein · github.com/pewresearch/prc-schema-seo · website

0stars
0forks

Install

No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:

wp plugin install https://github.com/pewresearch/prc-schema-seo/archive/refs/heads/trunk.zip

Readme

PRC Schema SEO

Provides schema generation, SEO meta tags, primary term management, preview panels, and site-level template defaults for titles & descriptions on Pew Research Center platform sites.

Features

  • JSON-LD schema generation with post-type level overrides
  • Meta tag output (title, description, canonical, robots, Open Graph, Twitter)
  • Primary term selection per taxonomy
  • Editor previews (search, social, chat, internal)
  • Site Editor sidebar for global pattern configuration and noindex lists
  • Extensible pattern token engine
  • AI-powered SEO suggestions (title, description, social text) via the prc-schema-seo/suggest WP AI ability
  • Real-Time Collaboration (RTC) compatible editor UI (WP 7.0+)
  • Auto-redirects on slug/term changes via Safe Redirect Manager integration
  • Redirect CSV import UI
  • IndexNow search engine notification on publish
  • Google Search Console URL Inspection integration
  • Reading score WP Ability
  • Parse.ly metadata via the official wp-parsely plugin (see below)

Requirements

Required plugins (declared in the plugin header Requires Plugins field):

  • prc-scripts — provides @prc/components, @prc/icons, and shared webpack configuration
  • prc-post-publish-pipeline — sync and async post lifecycle hooks used for cache invalidation, IndexNow, and Search Console

The plugin no longer depends on prc-platform-core. All shared JS components and scripts are sourced from prc-scripts.

Parse.ly (wp-parsely)

The platform uses Automattic’s wp-parsely on VIP. prc-schema-seo implements Parsely_Integration (includes/class-parsely-integration.php) so Pew SEO data (canonical URL, titles, authors, sections, keywords) is merged into Parse.ly’s metadata pipeline instead of maintaining a parallel tag system.

How it works

Context Behavior
Singular posts/pages (supported post types) wp_parsely_metadata and wp_parsely_permalink enrich Parse.ly’s array with PRC SEO fields from Metadata::get_seo_data() / resolve_for_display(). Whether the plugin emits JSON-LD or repeated <meta name="parsely-*"> tags follows Parse.ly’s own settings in WP Admin (meta_type and related options).
Static front page, category/tag/custom tax archives, post type archives PRC emits its own parsely-title / parsely-link / parsely-type meta tags from Parsely_Integration at wp_head priority 3, and suppresses wp-parsely's renderer by returning an empty array from wp_parsely_metadata (the renderer bails at its ! isset( $metadata['headline'] ) guard). Links are forced to the https scheme. This works for both json_ld and repeated_metas output formats.
RLS template post type PRC suppresses wp-parsely output for this post type by returning an empty array from wp_parsely_metadata; PRC does not merge Parse.ly metadata for it.

WordPress hooks used

Hook Purpose
wpvip_parsely_load_mu On local environment, return true so VIP’s Parse.ly MU integration loads (matches production behavior in dev).
wp_parsely_managed_options Forces force_https_canonicals to true so wp-parsely never rewrites non-post URLs to http://.
wp_parsely_metadata Two roles: (1) on singular tracked posts, map PRC fields into Parse.ly’s metadata array (headline, url, thumbnail, keywords, articleSection, author/creator, dates); (2) on the front page, term archives, post type archives, and RLS template singular, return an empty array to suppress wp-parsely's own renderer (which bails when headline is unset). The wp_parsely_should_insert_metadata filter is intentionally not used because wp-parsely evaluates it once at plugin init (before wp has fired), making conditional-tag-based gating unreliable.
wp_parsely_permalink Align Parse.ly link meta with the PRC canonical URL (prc_schema_seo_canonical_url filter applies); scheme forced to https.

Caching

Home, term, and post type archive Parse.ly HTML fragments are cached with wp_cache_* in group prc_schema_seo_parsely_07142026, TTL 1 hour, keys such as parsely_tags_home, parsely_tags_term_{term_id}, and parsely_tags_post_type_archive_{post_type}. Term and home/archive fragments are invalidated on term meta updates and blogname/home/siteurl option changes. The WP-CLI migration command can warm term cache via the same Parsely_Integration::warm_term_cache() path.

Operational notes

  • Canonical: Changes that affect prc_schema_seo_canonical_url or stored SEO data affect Parse.ly link and url fields after cache invalidation or TTL expiry.
  • Keywords / section: Built from category, formats, research-teams, and internal markers (get_parsely_tag_tokens, get_parsely_section); empty section is omitted so articleSection is not sent when there is no primary category name.
  • Troubleshooting: If Parse.ly tags are missing locally, confirm environment type is local (for MU loader), that wp-parsely is active, and that the current template is not one where insertion is intentionally disabled (see table above).

Pattern Tokens

Patterns can be set for title & description via Site Editor sidebar fields. The following tokens are available:

Static tokens:

%post_title%
%site_name%
%primary_category%
%post_type%
%year%
%author%
%categories%      (comma-separated list of category names)
%tags%            (comma-separated list of tag names)

Dynamic tokens:

%primary_term:taxonomy%   (chosen primary term for the taxonomy, falls back to first term)
%terms:taxonomy%          (comma-separated list of all term names for taxonomy)

Whitespace is normalized after replacement. Empty tokens resolve to an empty string.

Extending Tokens

Use the prc_schema_seo_pattern_tokens filter to register additional simple tokens (key/value pairs). Dynamic patterns should be handled separately (e.g. by also parsing custom placeholders inside a secondary filter if needed).

add_filter( 'prc_schema_seo_pattern_tokens', function( $tokens, $post_id ) {
    $modified = get_post( $post_id ) ? get_post_modified_time( 'Y-m-d', false, $post_id ) : '';
    $tokens['%modified_date%'] = $modified;
    return $tokens;
}, 10, 2 );

Filters Reference

All hooks use the prc_schema_seo_ prefix. Return values must match the documented type; invalid types are ignored and logged.

Schema Output

Filter Signature Purpose
prc_schema_seo_should_output_schema (bool $should, int $post_id) Gate schema emission for a post. Return false to suppress.
prc_schema_seo_minify_json (bool $minify) Control whether JSON-LD output is minified. Default false.
prc_schema_seo_schema_type_default (string $type, string $post_type, int $post_id) Override the default schema type for a post type.
prc_schema_seo_allowed_schema_types (array $types, string $post_type) Whitelist schema types available in the editor UI. Must return a flat array of strings.
prc_schema_seo_schema_data (array $schemas, int $post_id, array $seo_data) Modify the full schema graph array just before JSON-LD serialization.
// Example: mark a custom post type as SoftwareApplication
add_filter( 'prc_schema_seo_schema_type_default', function( $type, $post_type, $post_id ) {
    if ( 'tool' === $post_type ) {
        return 'SoftwareApplication';
    }
    return $type;
}, 10, 3 );

Schema Objects — Article / Person / WebPage

Filter Signature Purpose
prc_schema_seo_article_schema (Article $article, int $post_id, array $seo_data, string $schema_type) Adjust Article / NewsArticle / BlogPosting schema object before graph merge.
prc_schema_seo_person_schema (Person $person, int $post_id, array $seo_data) Adjust Person schema (used for staff post type and author term pages).
prc_schema_seo_webpage_schema (WebPage $webpage, int $post_id, array $seo_data) Adjust the final WebPage schema object.
prc_schema_seo_webpage_graph_item (WebPage $webpage, int $post_id, array $seo_data) Adjust the WebPage item specifically as a graph item reference before the full schema merge.
prc_schema_seo_breadcrumb_schema (BreadcrumbList $list, int $post_id, array $seo_data) Adjust the BreadcrumbList schema for a post.

Schema Objects — Organization

Filter Signature Purpose
prc_schema_seo_organization_schema (Organization $org, int $post_id) Adjust the fully assembled Organization schema object.
prc_schema_seo_organization_config (array $config) Override the Organization config array (name, URL, description, slogan, logo, social profiles). Replaces the full config; merge carefully.
prc_schema_seo_organization_name (string $name) Override the organization name string. Used across schema, AI prompts, and Yoast migration.
prc_schema_seo_organization_address (array $address) Override the postal address array (streetAddress, addressLocality, postalCode, addressCountry).
prc_schema_seo_same_as (array $urls) Override the sameAs URL array on the Organization schema.
prc_schema_seo_parent_organization (array $config) Override the parent organization config (name, url). Defaults to The Pew Charitable Trusts.

Read the full README on GitHub →