Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/GoogleForCreators/web-stories-wp/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Web Stories provides flexible archive page options, allowing you to use the default WordPress archive, disable archives entirely, or create a custom archive page.

Archive Configuration

The archive behavior is controlled through plugin settings:
Story_Post_Type.php
public function get_has_archive() {
    $archive_page_option = $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE );
    $has_archive         = true;
    
    if ( 'disabled' === $archive_page_option ) {
        $has_archive = false;
    } elseif ( 'custom' === $archive_page_option ) {
        $custom_archive_page_id = (int) $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );
        if ( $custom_archive_page_id && 'publish' === get_post_status( $custom_archive_page_id ) ) {
            $uri = get_page_uri( $custom_archive_page_id );
            if ( $uri ) {
                $has_archive = urldecode( $uri );
            }
        }
    }
    
    return $has_archive;
}

Archive Options

There are three archive display modes:

Standard WordPress Archive

Uses the built-in WordPress post type archive functionality.URL Structure:
https://example.com/web-stories/
Template Hierarchy:
  1. archive-web-story.php
  2. archive.php
  3. index.php
The default archive shows all published stories using your theme’s archive template.

Custom Archive Implementation

When a custom archive page is set, the plugin modifies the main query:
Story_Archive.php
public function pre_get_posts( WP_Query $query ): void {
    if ( ! \is_string( $this->story_post_type->get_has_archive() ) ) {
        return;
    }
    
    if ( $query->is_admin || ! $query->is_main_query() ) {
        return;
    }
    
    if ( ! $query->is_post_type_archive( $this->story_post_type->get_slug() ) ) {
        return;
    }
    
    $custom_archive_page_id = (int) $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );
    
    $query->set( 'page_id', $custom_archive_page_id );
    $query->set( 'post_type', 'page' );
    $query->is_post_type_archive = false;
    $query->is_archive           = false;
    $query->is_singular          = true;
    $query->is_page              = true;
}
The query is transformed from a post type archive to a singular page query, allowing full page template support.

Archive Page Redirects

The plugin handles redirects for the default /web-stories/ URL:
Story_Archive.php
public function redirect_post_type_archive_urls( $bypass, WP_Query $query ) {
    global $wp_rewrite;
    
    if ( $bypass || ! \is_string( $this->story_post_type->get_has_archive() ) || ( ! $wp_rewrite instanceof WP_Rewrite || ! $wp_rewrite->using_permalinks() ) ) {
        return $bypass;
    }
    
    // 'pagename' is for most permalink types, 'name' is for when %postname% is used as top-level.
    if ( $this->story_post_type::REWRITE_SLUG === $query->get( 'pagename' ) || $this->story_post_type::REWRITE_SLUG === $query->get( 'name' ) ) {
        $redirect_url = get_post_type_archive_link( $this->story_post_type->get_slug() );
        
        if ( $redirect_url && wp_safe_redirect( $redirect_url, 301 ) ) {
            exit;
        }
    }
    
    return $bypass;
}

Archive Page States

Custom archive pages show a special indicator in the WordPress admin:
Story_Archive.php
public function filter_display_post_states( $post_states, ?WP_Post $post ) {
    if ( ! \is_array( $post_states ) || ! $post ) {
        return $post_states;
    }
    
    if ( ! \is_string( $this->story_post_type->get_has_archive() ) ) {
        return $post_states;
    }
    
    $custom_archive_page_id = (int) $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );
    
    if ( $post->ID === $custom_archive_page_id ) {
        $post_states['web_stories_archive_page'] = __( 'Web Stories Archive Page', 'web-stories' );
    }
    
    return $post_states;
}
This adds a “Web Stories Archive Page” label in the pages list.

Archive Page Deletion

When a custom archive page is trashed or deleted, settings reset automatically:
Story_Archive.php
public function on_remove_archive_page( int $postid ): void {
    if ( 'page' !== get_post_type( $postid ) ) {
        return;
    }
    
    $custom_archive_page_id = (int) $this->settings->get_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID );
    
    if ( $custom_archive_page_id !== $postid ) {
        return;
    }
    
    $this->settings->update_setting( $this->settings::SETTING_NAME_ARCHIVE, 'default' );
    $this->settings->update_setting( $this->settings::SETTING_NAME_ARCHIVE_PAGE_ID, 0 );
}

Rewrite Rules

Changing archive settings triggers a rewrite flush:
Story_Archive.php
public function update_archive_setting(): void {
    $this->story_post_type->unregister_post_type();
    $this->story_post_type->register_post_type();
    
    if ( ! \defined( '\WPCOM_IS_VIP_ENV' ) || false === \WPCOM_IS_VIP_ENV ) {
        flush_rewrite_rules( false );
    }
}
Rewrite rules are not flushed on VIP environments. Use the WP-CLI command wp rewrite flush instead.

Creating a Custom Archive Template

Create a custom archive template in your theme:
1

Create Template File

Create archive-web-story.php in your theme directory.
2

Add Template Header

archive-web-story.php
<?php
/**
 * Template Name: Web Stories Archive
 * Description: Custom archive for Web Stories
 */

get_header();
?>
3

Query Stories

<div class="web-stories-archive">
    <h1><?php post_type_archive_title(); ?></h1>
    
    <?php
    $args = [
        'post_type'      => 'web-story',
        'posts_per_page' => 12,
        'paged'          => get_query_var( 'paged' ) ?: 1,
    ];
    
    $stories_query = new WP_Query( $args );
    
    if ( $stories_query->have_posts() ) :
        while ( $stories_query->have_posts() ) :
            $stories_query->the_post();
            // Display story
        endwhile;
        
        // Pagination
        the_posts_pagination();
    endif;
    
    wp_reset_postdata();
    ?>
</div>
4

Add Footer

<?php get_footer(); ?>

Using Story_Query in Templates

Use the Story_Query class for advanced story displays:
$story_attrs = [
    'view_type'         => 'grid',
    'number_of_columns' => 3,
    'show_title'        => true,
    'show_author'       => true,
    'show_date'         => true,
];

$story_args = [
    'posts_per_page' => 12,
    'orderby'        => 'post_date',
    'order'          => 'DESC',
];

$story_query = new Google\Web_Stories\Story_Query( $story_attrs, $story_args );
echo $story_query->render();
Get the archive link programmatically:
$archive_url = get_post_type_archive_link( 'web-story' );

if ( $archive_url ) {
    echo '<a href="' . esc_url( $archive_url ) . '">View All Stories</a>';
}
The function returns false if archives are disabled.

Pagination

Implement pagination in custom archive templates:
the_posts_pagination([
    'mid_size'  => 2,
    'prev_text' => __( 'Previous Stories', 'textdomain' ),
    'next_text' => __( 'More Stories', 'textdomain' ),
]);

Archive Page Hooks

The archive system uses WordPress hooks:
// Fires when archive setting is added
add_action( 'add_option_web_stories_archive', 'my_archive_callback' );

// Fires when archive setting is updated  
add_action( 'update_option_web_stories_archive', 'my_archive_callback' );

// Fires when archive page ID is updated
add_action( 'update_option_web_stories_archive_page_id', 'my_archive_callback' );

SEO Considerations

Customize the archive page title using SEO plugins or the document_title_parts filter:
add_filter( 'document_title_parts', function( $title ) {
    if ( is_post_type_archive( 'web-story' ) ) {
        $title['title'] = 'Our Web Stories';
    }
    return $title;
});
Add a custom description to your archive template:
if ( is_post_type_archive( 'web-story' ) ) {
    echo '<meta name="description" content="Browse our collection of engaging Web Stories">';
}
The plugin automatically adds structured data for stories. You can extend it for the archive page using the web_stories_schema filter.

Best Practices

Performance

  • Limit stories per page (12-20 recommended)
  • Use lazy loading for images
  • Enable caching for archive pages
  • Use no_found_rows when pagination isn’t needed

User Experience

  • Provide filtering/sorting options
  • Show clear pagination
  • Include search functionality
  • Display story metadata (author, date)

Content Strategy

  • Feature latest/popular stories
  • Organize by categories
  • Add featured story sections
  • Include related content

Mobile Design

  • Use responsive grid layouts
  • Optimize touch targets
  • Test swipe gestures
  • Ensure fast load times

Next Steps

WordPress Integration

Learn about the custom post type

Gutenberg Blocks

Embed stories with blocks