Skip to main content

Overview

Web Stories integrates deeply with WordPress as a custom post type (web-story), providing native support for WordPress features like posts, taxonomies, and archives.

Custom Post Type

The Web Stories plugin registers a custom post type with the slug web-story that appears in the WordPress admin menu.

Post Type Configuration

The story post type is defined in includes/Story_Post_Type.php:
Story_Post_Type.php
class Story_Post_Type extends Post_Type_Base {
    public const POST_TYPE_SLUG = 'web-story';
    public const REWRITE_SLUG = 'web-stories';
}

Supported Features

Stories support the following WordPress features:
  • Title - Used for amp-story[title] attribute
  • Author - Standard WordPress author support
  • Editor - Custom story editor interface
  • Excerpt - Story description/summary
  • Thumbnail - Used for poster images
  • Revisions - Full revision history support
  • Custom Fields - Meta data storage

URL Structure

Stories use the rewrite slug web-stories by default:
https://example.com/web-stories/my-story-title/
The rewrite configuration supports:
  • Pretty permalinks with custom slug
  • No front base (with_front => false)
  • RSS feeds for stories

Taxonomies

Stories support standard WordPress taxonomies and custom taxonomies. You can:
  • Assign categories to stories
  • Add tags for organization
  • Create custom taxonomies for story classification
  • Filter stories by taxonomy in queries

Capabilities & Permissions

The plugin defines custom capabilities for granular permission control:
'capability_type' => [ 'web-story', 'web-stories' ],
'map_meta_cap'    => true,
This creates capabilities like:
  • edit_web-story
  • edit_web-stories
  • publish_web-stories
  • delete_web-stories

Post States

Stories integrate with WordPress post states to show their status in the admin:
Story_Post_Type.php
public function bulk_post_updated_messages( $bulk_messages, $bulk_counts ) {
    $bulk_messages[ $this->get_slug() ] = [
        'updated'   => _n( '%s story updated.', '%s stories updated.', $bulk_counts['updated'] ),
        'deleted'   => _n( '%s story permanently deleted.', '%s stories permanently deleted.', $bulk_counts['deleted'] ),
        'trashed'   => _n( '%s story moved to the Trash.', '%s stories moved to the Trash.', $bulk_counts['trashed'] ),
    ];
    return $bulk_messages;
}

REST API Integration

Stories are fully exposed through the WordPress REST API:
'show_in_rest'          => true,
'rest_namespace'        => 'web-stories/v1',
'rest_controller_class' => Stories_Controller::class,
Access stories via:
GET /wp-json/web-stories/v1/web-story
GET /wp-json/web-stories/v1/web-story/{id}

Admin Menu Icon

The plugin uses a custom SVG icon in the WordPress admin menu:
Story_Post_Type.php
protected function get_post_type_icon(): string {
    return 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0i...';
}

Cache Management

The plugin manages WordPress object cache for story post counts:
Story_Post_Type.php
public function clear_user_posts_count( int $post_id, WP_Post $post ): void {
    if ( $this->get_slug() !== $post->post_type ) {
        return;
    }
    
    $cache_key   = "count_user_{$post->post_type}_{$post->post_author}";
    $cache_group = 'user_posts_count';
    wp_cache_delete( $cache_key, $cache_group );
}

Filters & Hooks

The plugin provides WordPress filters and actions:

Available Filters

  • web_stories_block_settings - Modify block configuration
  • widget_title - Filter widget titles
  • display_post_states - Add custom post states

Available Actions

  • web_stories_story_published - Fires when a story is published
  • web_stories_story_updated - Fires when a story is updated
The Web Stories custom post type is excluded from WordPress search by default (exclude_from_search => true).

Next Steps

Gutenberg Blocks

Learn how to embed stories using blocks

Story Archives

Configure story archive pages

Build docs developers (and LLMs) love