Skip to main content
< All Topics
Print

WordPress SEO Plugin Integration

name: wordpress-seo-plugin-integration

description: Integration patterns for reading from and writing to WordPress SEO plugins (Yoast, Rank Math, AIOSEO, SEOPress). Data storage formats, APIs, hooks, meta field conventions. Use when building plugins that need to read or write SEO data, integrating with multiple SEO plugins, accessing focus keyphrases or meta descriptions programmatically, or building SEO data migration tools.

WordPress SEO Plugin Integration

Instructions

Implement cross-compatible integration with the four major WordPress SEO plugins. Products that manage SEO data must detect which plugin is active and use the correct APIs, hooks, and storage formats.

1. Plugin Detection

Detect the active SEO plugin before any read/write operations:


function detect_seo_plugin(): string {
    if ( defined( 'WPSEO_VERSION' ) ) {
        return 'yoast';
    }
    if ( defined( 'RANK_MATH_VERSION' ) ) {
        return 'rankmath';
    }
    if ( defined( 'AIOSEO_VERSION' ) ) {
        return 'aioseo';
    }
    if ( defined( 'SEOPRESS_VERSION' ) ) {
        return 'seopress';
    }
    return 'none';
}

Cache the result with wp_cache_set() since this runs frequently.

2. Meta Field Storage Formats

Each plugin stores SEO data in different postmeta keys:

Focus Keyphrase

Plugin Meta Key Format
Yoast _yoast_wpseo_focuskw Plain string
Rank Math rank_math_focus_keyword Comma-separated string (multiple keywords)
AIOSEO _aioseo_keywords JSON string: [{"keyword":"term","score":0}]
SEOPress _seopress_analysis_target_kw Comma-separated string

Meta Title

Plugin Meta Key Format
Yoast _yoast_wpseo_title String with %% variables: %%title%% %%sep%% %%sitename%%
Rank Math rank_math_title String with % variables: %title% %sep% %sitename%
AIOSEO _aioseo_title String with # tags: #post_title #separator_sa #site_title
SEOPress _seopress_titles_title Plain string (variables resolved at render)

Meta Description

Plugin Meta Key Format
Yoast _yoast_wpseo_metadesc Plain string
Rank Math rank_math_description Plain string
AIOSEO _aioseo_description Plain string
SEOPress _seopress_titles_desc Plain string

Canonical URL

Plugin Meta Key Format
Yoast _yoast_wpseo_canonical URL string
Rank Math rank_math_canonical_url URL string
AIOSEO _aioseo_canonical_url URL string
SEOPress _seopress_robots_canonical URL string

Open Graph Title / Description

Plugin OG Title Key OG Description Key
Yoast _yoast_wpseo_opengraph-title _yoast_wpseo_opengraph-description
Rank Math rank_math_facebook_title rank_math_facebook_description
AIOSEO _aioseo_og_title _aioseo_og_description
SEOPress _seopress_social_fb_title _seopress_social_fb_desc

3. Unified Read/Write Interface

Abstract plugin differences behind a unified interface:


interface SEO_Data_Provider {
    public function get_focus_keyphrase( int $post_id ): string;
    public function set_focus_keyphrase( int $post_id, string $keyphrase ): bool;
    public function get_meta_title( int $post_id ): string;
    public function set_meta_title( int $post_id, string $title ): bool;
    public function get_meta_description( int $post_id ): string;
    public function set_meta_description( int $post_id, string $description ): bool;
    public function get_canonical_url( int $post_id ): string;
    public function set_canonical_url( int $post_id, string $url ): bool;
    public function get_og_title( int $post_id ): string;
    public function set_og_title( int $post_id, string $title ): bool;
    public function get_og_description( int $post_id ): string;
    public function set_og_description( int $post_id, string $description ): bool;
    public function get_robots_meta( int $post_id ): array;
    public function set_robots_meta( int $post_id, array $directives ): bool;
}

Implement one class per plugin (Yoast_SEO_Provider, RankMath_SEO_Provider, etc.) and use a factory:


function get_seo_provider(): SEO_Data_Provider {
    return match ( detect_seo_plugin() ) {
        'yoast'    => new Yoast_SEO_Provider(),
        'rankmath' => new RankMath_SEO_Provider(),
        'aioseo'   => new AIOSEO_SEO_Provider(),
        'seopress' => new SEOPress_SEO_Provider(),
        default    => new Null_SEO_Provider(),
    };
}

4. Plugin-Specific APIs and Hooks

Yoast SEO

Programmatic API (preferred over direct meta):


// Read via helper
$meta = YoastSEO()->meta->for_post( $post_id );
$title = $meta->title;
$description = $meta->description;

// Hooks for modifying output
add_filter( 'wpseo_title', function( $title ) { return $title; } );
add_filter( 'wpseo_metadesc', function( $desc ) { return $desc; } );
add_filter( 'wpseo_canonical', function( $canonical ) { return $canonical; } );

Rank Math


// Read
$keyphrase = RankMath\Post::get_meta( 'focus_keyword', $post_id );
$description = RankMath\Post::get_meta( 'description', $post_id );

// Hooks
add_filter( 'rank_math/frontend/title', function( $title ) { return $title; } );
add_filter( 'rank_math/frontend/description', function( $desc ) { return $desc; } );

AIOSEO


// Read via model
$aioseo_post = \AIOSEO\Plugin\Models\Post::getPost( $post_id );
$title = $aioseo_post->title;
$description = $aioseo_post->description;
$keyphrases = json_decode( $aioseo_post->keyphrases, true );

SEOPress


// Direct meta access (no public PHP API)
$title = get_post_meta( $post_id, '_seopress_titles_title', true );
$desc  = get_post_meta( $post_id, '_seopress_titles_desc', true );

// Hooks
add_filter( 'seopress_titles_title', function( $title ) { return $title; } );
add_filter( 'seopress_titles_desc', function( $desc ) { return $desc; } );

5. Robots Meta Directives

Each plugin stores robots directives differently:

Plugin Storage noindex Key
Yoast _yoast_wpseo_meta-robots-noindex 1 = noindex
Rank Math rank_math_robots Serialized array: ['noindex']
AIOSEO _aioseo_robots_noindex Boolean
SEOPress _seopress_robots_index yes = noindex

6. Schema/Structured Data Integration

When adding custom schema alongside the SEO plugin’s schema:

  • Yoast: Use wpseo_schema_graph filter to add to the schema graph
  • Rank Math: Use rank_math/json_ld filter
  • AIOSEO: Use aioseo_schema_output filter
  • SEOPress: Use seopress_schemas_auto_json_ld filter

Avoid outputting duplicate schemas. Check if the SEO plugin already outputs Article, Organization, or WebPage schema before adding your own.

7. REST API Endpoints

Some plugins expose REST API endpoints:

Plugin Namespace Key Endpoints
Yoast /yoast/v1/ Limited — primarily internal use
Rank Math /rankmath/v1/ updateMeta, getHead
AIOSEO /aioseo/v1/ Full CRUD for SEO data
SEOPress /seopress/v1/ Limited endpoints

For cross-plugin compatibility, prefer direct postmeta read/write over REST APIs since not all plugins expose comprehensive endpoints.

8. Data Migration Between Plugins

When building migration tools:

  1. Read all SEO data from source plugin using the unified interface
  2. Map fields to target plugin format (handle variable syntax conversion)
  3. Write to target plugin’s meta keys
  4. Verify by reading back through the target plugin’s API
  5. Preserve original data in a backup meta key: _seo_migration_backup_{source}

Variable conversion table:

  • Yoast %%title%% → Rank Math %title% → AIOSEO #post_title → SEOPress (resolved at save)
  • Yoast %%sep%% → Rank Math %sep% → AIOSEO #separator_sa → SEOPress (literal separator)

Inputs Required

  • Target SEO plugin(s) to integrate with (one or all four)
  • Read vs. write requirements (some integrations only need to read existing data)
  • Fields to access (keyphrase, meta title, meta description, OG, robots, schema)
  • WordPress version and PHP version constraints
  • Whether REST API integration is needed alongside PHP
  • Migration requirements (if switching between plugins)

Output Format

  • Plugin detection implementation
  • Unified SEO data provider interface and plugin-specific implementations
  • Meta key reference table for target fields
  • Hook integration points for output modification
  • Schema integration code avoiding duplicates
  • Migration utility (if needed)
  • Unit test coverage for each plugin adapter

Anti-Patterns

  • Hardcoding a single plugin: Always implement the detection + provider pattern. Users switch SEO plugins, and your integration should survive the switch.
  • Writing directly to meta without sanitization: SEO fields are rendered in . Sanitize all values for HTML output: esc_attr() for meta values, esc_url() for canonical URLs.
  • Ignoring variable syntax differences: Writing Yoast %%title%% variables into Rank Math fields produces broken output. Always convert between formats.
  • Overwriting user-edited SEO data without confirmation: If the user has manually set a meta description, don’t silently replace it. Warn or offer a merge.
  • Outputting duplicate schema: Two Organization schemas on one page confuses search engines. Check what the SEO plugin already outputs.
  • Assuming all plugins have APIs: SEOPress has minimal PHP API — you’ll need direct postmeta access. Plan for the lowest common denominator.
  • Not testing with each plugin active: Integration that works with Yoast may break with Rank Math. Test with each plugin individually and with no SEO plugin installed (the Null_SEO_Provider path).
Table of Contents