Time-based meta title/description rotation for SEO split testing. Rank Forge rotates the meta title and description by week: the variant depends on the date, not on the visitor. PRO feature.
How It Works
- Test starts immediately when enabled
- Week 1: Variant A (original meta title/description) is served
- Week 2: Variant B (alternate meta title/description) is served
- Alternates weekly until disabled
- In any one week every request gets the same variant, whether it comes from a visitor or from a crawler (a page cache can keep sending the page it made earlier)
The variant is determined by: floor((time() - start_time) / WEEK_IN_SECONDS) % 2 — when 0, variant A is active; when 1, variant B.
Implementation Details
On wp_head (priority 0, before all meta output):
RANKFORGE_AB_Testing::maybe_swap_metachecks if A/B testing is enabled- If variant B is active and has a title, it is given through the
pre_get_document_titlefilter (priorityPHP_INT_MAX, for the post under test only) and through therankforge_meta_titlefilter, the title of<meta name="title">,og:titleandtwitter:title - If variant B is active and has a description, it is given through the
rankforge_meta_descriptionfilter, so the page still prints one<meta name="description">tag (and the og and twitter descriptions), now with Description B - The page view counter of the variant shown is incremented (
_rankforge_ab_served_aor_rankforge_ab_served_b; bots are left out)
Programmatic Control
php
$post_id = 42;
// Start an A/B test
update_post_meta( $post_id, '_rankforge_ab_enabled', true );
update_post_meta( $post_id, '_rankforge_ab_title_b', 'Alternative Title | MyBlog' );
update_post_meta( $post_id, '_rankforge_ab_desc_b', 'Alternative description for testing.' );
update_post_meta( $post_id, '_rankforge_ab_start', time() );
update_post_meta( $post_id, '_rankforge_ab_served_a', 0 );
update_post_meta( $post_id, '_rankforge_ab_served_b', 0 );
// Check current state
$current = get_post_meta( $post_id, '_rankforge_ab_current', true ); // 'a' or 'b'
$served_a = (int) get_post_meta( $post_id, '_rankforge_ab_served_a', true );
$served_b = (int) get_post_meta( $post_id, '_rankforge_ab_served_b', true );
// Declare a winner and keep variant B
$title_b = get_post_meta( $post_id, '_rankforge_ab_title_b', true );
$desc_b = get_post_meta( $post_id, '_rankforge_ab_desc_b', true );
update_post_meta( $post_id, '_rankforge_meta_title', $title_b );
update_post_meta( $post_id, '_rankforge_meta_description', $desc_b );
update_post_meta( $post_id, '_rankforge_ab_enabled', false );
// Bulk-stop all running A/B tests
$active = get_posts( [
'post_type' => 'any', 'posts_per_page' => -1, 'fields' => 'ids',
'meta_query' => [ [ 'key' => '_rankforge_ab_enabled', 'value' => '1' ] ],
] );
foreach ( $active as $pid ) {
update_post_meta( $pid, '_rankforge_ab_enabled', false );
}Analyzing Test Results
php
// Compare variant performance using page view counts
$post_id = 42;
$served_a = (int) get_post_meta( $post_id, '_rankforge_ab_served_a', true );
$served_b = (int) get_post_meta( $post_id, '_rankforge_ab_served_b', true );
$start = (int) get_post_meta( $post_id, '_rankforge_ab_start', true );
$weeks = floor( ( time() - $start ) / WEEK_IN_SECONDS );
echo "Test running for {$weeks} weeks\n";
echo "Variant A served: {$served_a} times\n";
echo "Variant B served: {$served_b} times\n";
// For CTR analysis, combine with GSC data
if ( class_exists( 'RANKFORGE_GSC' ) && RANKFORGE_GSC::instance()->is_connected() ) {
$page_url = get_permalink( $post_id );
$rankings = RANKFORGE_GSC::instance()->get_page_rankings( $page_url, 28 );
// Compare CTR during variant A vs variant B periods
}—