This document provides a comprehensive overview of the document model and relationships between post types, meta fields, and taxonomies across the PRC-* plugins in the Pew Research Center WordPress platform.
Architecture Overview
The PRC Platform uses a modular plugin architecture where:
- Post types define content entities (articles, staff, datasets, etc.)
- Taxonomies provide classification and organization (topics, teams, formats)
- Meta fields store additional structured data on posts
- Term Data Store (TDS) pattern links post types to taxonomies for hybrid content
Visual Diagram
erDiagram
%% ===========================================
%% CORE CONTENT POST TYPES
%% ===========================================
POST {
int ID PK
string post_title
text post_content
string post_status
datetime post_date
}
FEATURE {
int ID PK
string post_title
text post_content
string _feature_dev_notes
array _feature_rewrites
}
QUIZ {
int ID PK
string post_title
text post_content
object _report
}
CHART {
int ID PK
string post_title
text post_content
}
DATASET {
int ID PK
string post_title
text post_content
int _download_attachment_id
int _total_downloads
boolean is_atp
string dataset_schema
}
COLLECTIONS {
int ID PK
string post_title
text post_content
string kicker_pattern_slug
}
%% ===========================================
%% STAFF & BYLINES
%% ===========================================
STAFF {
int ID PK
string post_title
text post_content
string jobTitle
string jobTitleExtended
boolean bylineLinkEnabled
object _maelstrom
array socialProfiles
}
%% ===========================================
%% UTILITY POST TYPES
%% ===========================================
HOMEPAGE {
int ID PK
string post_title
text post_content
}
BLOCK_MODULE {
int ID PK
string post_title
text post_content
array _story_item_ids
}
NOTE {
int ID PK
string post_title
text post_content
array shared_with_users
}
DATA_TABLE {
int ID PK
string post_title
text post_content
}
DOCUMENTATION {
int ID PK
string post_title
text post_content
}
RELEASE_NOTE {
int ID PK
string post_title
text post_content
}
RLS_TEMPLATE {
int ID PK
string post_title
text post_content
}
%% ===========================================
%% TAXONOMIES
%% ===========================================
CATEGORY {
int term_id PK
string name
string slug
int parent
}
RESEARCH_TEAMS {
int term_id PK
string name
string slug
int parent
}
FORMATS {
int term_id PK
string name
string slug
}
BYLINES {
int term_id PK
string name
string slug
boolean is_guest_author
}
COLLECTION_TAX {
int term_id PK
string name
string slug
int parent
}
DATASETS_TAX {
int term_id PK
string name
string slug
int parent
}
REGIONS_COUNTRIES {
int term_id PK
string name
string slug
int parent
}
LANGUAGES {
int term_id PK
string name
string slug
}
AREAS_OF_EXPERTISE {
int term_id PK
string name
string slug
int parent
}
STAFF_TYPE {
int term_id PK
string name
string slug
int parent
}
FUND_POOLS {
int term_id PK
string name
string slug
string funder_url
string funder_id
float _funder_budget
}
MODE_OF_ANALYSIS {
int term_id PK
string name
string slug
}
POST_VISIBILITY {
int term_id PK
string name
string slug
}
BLOCK_AREA {
int term_id PK
string name
string slug
int parent
}
LEVEL_OF_EFFORT {
int term_id PK
string name
string slug
}
PRIMARY_AUDIENCE {
int term_id PK
string name
string slug
}
INFORMATION_TYPE {
int term_id PK
string name
string slug
}
DECODED_CATEGORY {
int term_id PK
string name
string slug
}
%% ===========================================
%% RELATIONSHIPS - Core Post Type
%% ===========================================
POST ||--o{ CATEGORY : "has topics"
POST ||--o{ RESEARCH_TEAMS : "belongs to"
POST ||--o{ FORMATS : "has format"
POST ||--o{ BYLINES : "authored by"
POST ||--o{ COLLECTION_TAX : "part of"
POST ||--o{ DATASETS_TAX : "has dataset"
POST ||--o{ REGIONS_COUNTRIES : "covers"
POST ||--o{ LANGUAGES : "written in"
POST ||--o{ POST_VISIBILITY : "visibility"
%% ===========================================
%% RELATIONSHIPS - Feature
%% ===========================================
FEATURE ||--o{ CATEGORY : "has topics"
FEATURE ||--o{ RESEARCH_TEAMS : "belongs to"
FEATURE ||--o{ BYLINES : "authored by"
FEATURE ||--o{ DATASETS_TAX : "has dataset"
FEATURE ||--o{ COLLECTION_TAX : "part of"
FEATURE ||--o{ REGIONS_COUNTRIES : "covers"
%% ===========================================
%% RELATIONSHIPS - Quiz
%% ===========================================
QUIZ ||--o{ CATEGORY : "has topics"
QUIZ ||--o{ RESEARCH_TEAMS : "belongs to"
QUIZ ||--o{ BYLINES : "authored by"
QUIZ ||--o{ DATASETS_TAX : "has dataset"
QUIZ ||--o{ COLLECTION_TAX : "part of"
QUIZ ||--o{ LEVEL_OF_EFFORT : "effort level"
QUIZ ||--o{ PRIMARY_AUDIENCE : "audience"
QUIZ ||--o{ INFORMATION_TYPE : "info type"
%% ===========================================
%% RELATIONSHIPS - Chart
%% ===========================================
CHART ||--o{ CATEGORY : "has topics"
CHART ||--o{ DATASETS_TAX : "has dataset"
%% ===========================================
%% TERM DATA STORE RELATIONSHIPS
%% (Post Type <-> Taxonomy Hybrid Pattern)
%% ===========================================
STAFF ||--|| BYLINES : "TDS linked"
COLLECTIONS ||--|| COLLECTION_TAX : "TDS linked"
DATASET ||--|| DATASETS_TAX : "TDS linked"
%% ===========================================
%% STAFF RELATIONSHIPS
%% ===========================================
STAFF ||--o{ AREAS_OF_EXPERTISE : "expertise in"
STAFF ||--o{ STAFF_TYPE : "type of"
STAFF ||--o{ RESEARCH_TEAMS : "member of"
%% ===========================================
%% COLLECTIONS RELATIONSHIPS
%% ===========================================
COLLECTIONS ||--o{ POST_VISIBILITY : "visibility"
COLLECTIONS ||--o{ BYLINES : "curated by"
%% ===========================================
%% DATASET RELATIONSHIPS
%% ===========================================
DATASET }o--|| POST : "associated with"
DATASET }o--|| FEATURE : "associated with"
DATASET }o--|| CHART : "associated with"
DATASET }o--|| QUIZ : "associated with"
%% ===========================================
%% BLOCK MODULE RELATIONSHIPS
%% ===========================================
BLOCK_MODULE ||--o{ BLOCK_AREA : "placed in"
BLOCK_MODULE ||--o{ CATEGORY : "for topic"
BLOCK_MODULE ||--o{ REGIONS_COUNTRIES : "for region"
BLOCK_MODULE ||--o{ COLLECTION_TAX : "for collection"
%% ===========================================
%% DECODED RELATIONSHIPS
%% ===========================================
POST ||--o{ DECODED_CATEGORY : "decoded in"
Post Types Reference
Content Post Types
| Post Type | Plugin | Description | Key Meta Fields |
|---|---|---|---|
post | Core WP | Standard blog posts/articles | bylines, acknowledgements, displayBylines, reportMaterials, multiSectionReport |
feature | prc-interactive-features | Interactive data visualizations | _feature_rewrites, _feature_dev_notes |
quiz | prc-quiz-builder | Interactive quizzes | _report |
chart | prc-chart-builder | Data visualizations/charts | – |
dataset | prc-datasets | Downloadable datasets | _download_attachment_id, _total_downloads, is_atp, dataset_schema |
collections | prc-collections | Curated content collections | kicker_pattern_slug |
rls_template | prc-religious-landscape-study | RLS page templates | – |
Staff & Bylines
| Post Type | Plugin | Description | Key Meta Fields |
|---|---|---|---|
staff | prc-staff-bylines | Staff member profiles | jobTitle, jobTitleExtended, bylineLinkEnabled, _maelstrom, socialProfiles |
Utility Post Types
| Post Type | Plugin | Description | Key Meta Fields |
|---|---|---|---|
homepage | prc-homepages | Homepage layouts | – |
block_module | prc-block-area-modules | Reusable block modules | _story_item_ids |
note | prc-notes | Internal editorial notes | shared_with_users |
documentation | prc-wiki | Platform documentation | – |
release-note | prc-wiki | Release notes | – |
Post-Like Types (via prc-post-like-types)
These post types use date-based permalinks like standard posts:
short-readfact-sheetdecodedpress-releasestub
Default taxonomies: category, collection, formats, languages, research-teams
Page-Like Types (via prc-page-like-types)
These post types behave like pages with hierarchical URLs.
Default taxonomies: category, collection, formats, languages, research-teams
Taxonomies Reference
Core Classification Taxonomies
| Taxonomy | Plugin | Description | Post Types |
|---|---|---|---|
category | prc-platform-core | Topics (renamed from "Categories") | post, feature, quiz, chart, block_module, and post-like types |
research-teams | prc-platform-core | Research teams (primary for permalinks) | post, feature, quiz, staff, dataset, fact-sheet, etc. |
formats | prc-platform-core | Content formats | post, short-read, fact-sheet, feature, quiz, decoded, dataset, etc. |
regions-countries | prc-platform-core | Geographic coverage | post, feature, fact-sheet, short-read, quiz, block_module |
languages | prc-platform-core | Content language | post, fact-sheet, stub, decoded, short-read |
mode-of-analysis | prc-platform-core | Research methodology | Various research post types |
fund-pools | prc-platform-core | Funding sources | Various post types |
decoded-category | prc-platform-core | Decoded blog categories | decoded |
Linked Taxonomies (Term Data Store Pattern)
| Taxonomy | Post Type | Plugin | Description |
|---|---|---|---|
bylines | staff | prc-staff-bylines | Links staff profiles to byline terms |
collection | collections | prc-collections | Links collection posts to collection terms |
datasets | dataset | prc-datasets | Links dataset posts to dataset terms |
Staff-Specific Taxonomies
| Taxonomy | Plugin | Description |
|---|---|---|
areas-of-expertise | prc-staff-bylines | Staff expertise areas |
staff-type | prc-staff-bylines | Staff classification (staff, executive-team, managing-directors, former) |
Utility Taxonomies
| Taxonomy | Plugin | Description |
|---|---|---|
_post_visibility | prc-platform-core | Controls post visibility (hidden-on-index, hidden-on-search) |
block_area | prc-block-area-modules | Block module placement areas |
Lookbook Taxonomies
| Taxonomy | Plugin | Description |
|---|---|---|
level_of_effort | prc-lookbook | Project effort classification |
primary_audience | prc-lookbook | Target audience |
information_type | prc-lookbook | Content information type |
Key Patterns & Relationships
Term Data Store (TDS) Pattern
The TDS pattern creates a one-to-one relationship between a post type and a taxonomy term, enabling hybrid content where:
- The post stores rich content (editor blocks, meta fields)
- The term provides taxonomy relationships to other content
staff (post) <--TDS--> bylines (taxonomy)
collections (post) <--TDS--> collection (taxonomy)
dataset (post) <--TDS--> datasets (taxonomy)
This allows posts to be attached to the taxonomy term automatically, and the term archive acts as the public URL.
Plugin Opt-In System
Plugins opt their post types into features using the WordPress native post_type_supports() pattern via the supports array in register_post_type():
// Register a post type with feature supports
register_post_type( 'my-post-type', array(
'supports' => array(
'title',
'editor',
'thumbnail',
// PRC Platform feature supports
'prc-schema-seo', // SEO meta fields and schema.org output
'prc-bylines', // Staff bylines and acknowledgements
'prc-art-direction', // Art direction image slots
'prc-sitemap', // Include in XML sitemap
'prc-related-posts', // Related posts functionality
'prc-datasets', // Datasets taxonomy attachment
'prc-collections', // Collections taxonomy attachment
'prc-publish-workflows', // Watchers + publish-pipeline REST/meta on this CPT
),
// ... other args
));
You can also add support after registration using add_post_type_support():
// Add support after registration
add_action( 'init', function() {
add_post_type_support( 'my-post-type', 'prc-bylines' );
add_post_type_support( 'my-post-type', 'prc-art-direction' );
}, 5 );
For publication listing and the main RSS feed, declare post type support (see prc-publication-listing):
add_post_type_support( 'my-post-type', 'prc-publication-listing' );
That opts the type into publication listing queries and into the main site feed. You can still use prc_platform_pub_listing_default_args for other query tweaks if needed.
Available Support Keys:
| Support Key | Description | Provider Plugin |
|---|---|---|
prc-schema-seo | SEO meta fields and schema.org output | prc-schema-seo |
prc-social | Social sharing metadata | prc-social |
prc-bylines | Staff bylines and acknowledgements | prc-staff-bylines |
prc-art-direction | Art direction image slots | prc-art-direction |
prc-sitemap | Include in XML sitemap | prc-schema-sitemap |
prc-related-posts | Related posts functionality | prc-related-posts |
prc-datasets | Datasets taxonomy attachment | prc-datasets |
prc-collections | Collections taxonomy attachment | prc-collections |
prc-publish-workflows | Watchers list, workflow notifications, and related REST fields on supported posts | prc-publish-workflows |
The built-in post type gets this support from prc-publish-workflows automatically (add_post_type_support( 'post', 'prc-publish-workflows' ) on init). Custom post types must add the key to their supports array (or call add_post_type_support()) so get_post_types_by_support( 'prc-publish-workflows' ) includes them when registering meta and REST fields.
Common Meta Fields Across Post Types
Several meta fields are registered across multiple post types:
| Meta Key | Description | Registered By |
|---|---|---|
bylines | Array of byline term references | prc-staff-bylines |
acknowledgements | Array of acknowledgement references | prc-staff-bylines |
displayBylines | Boolean to show/hide bylines | prc-staff-bylines |
reportMaterials | Report package materials | prc-report-package |
multiSectionReport | Multi-section report chapters | prc-report-package |
package_parts__enabled | Enable TOC parts | prc-report-package |
package_parts | TOC parts data | prc-report-package |
_datacite_doi | DataCite DOI | prc-schema-academic-identity |
prc_shortlink | Short link URL | prc-platform-core |
primary_term_id | Primary category term | prc-platform-core |
Post Type Registration Diagram
flowchart TB
subgraph Core["prc-platform-core"]
direction TB
Taxonomies["Shared Taxonomies
- category
- research-teams
- formats
- regions-countries
- languages
- fund-pools
- mode-of-analysis
- _post_visibility"]
end
subgraph PostLike["prc-post-like-types"]
direction TB
PLRegistry["Registry System"]
ShortRead["short-read"]
FactSheet["fact-sheet"]
Decoded["decoded"]
PressRelease["press-release"]
Stub["stub"]
end
subgraph PageLike["prc-page-like-types"]
direction TB
PGRegistry["Registry System"]
end
subgraph StaffBylines["prc-staff-bylines"]
direction TB
Staff["staff (post type)"]
Bylines["bylines (taxonomy)"]
Expertise["areas-of-expertise"]
StaffType["staff-type"]
Staff <-.TDS.-> Bylines
end
subgraph Collections["prc-collections"]
direction TB
CollPT["collections (post type)"]
CollTax["collection (taxonomy)"]
CollPT <-.TDS.-> CollTax
end
subgraph Datasets["prc-datasets"]
direction TB
DataPT["dataset (post type)"]
DataTax["datasets (taxonomy)"]
DataPT <-.TDS.-> DataTax
end
subgraph Interactive["prc-interactive-features"]
Feature["feature (post type)"]
end
subgraph ChartBuilder["prc-chart-builder"]
Chart["chart (post type)"]
end
subgraph QuizBuilder["prc-quiz-builder"]
Quiz["quiz (post type)"]
end
subgraph BlockArea["prc-block-area-modules"]
BlockModule["block_module (post type)"]
BlockAreaTax["block_area (taxonomy)"]
end
subgraph Homepages["prc-homepages"]
Homepage["homepage (post type)"]
end
subgraph Notes["prc-notes"]
Note["note (post type)"]
end
Core --> PostLike
Core --> PageLike
Core --> StaffBylines
Core --> Collections
Core --> Datasets
Core --> Interactive
Core --> ChartBuilder
Core --> QuizBuilder
Core --> BlockArea
Core --> Homepages
Core --> Notes
StaffBylines --> PostLike
Collections --> PostLike
Datasets --> Interactive
Datasets --> ChartBuilder
Datasets --> QuizBuilder
Publication Listing Integration
The Publication Listing system (prc-platform-core) manages which post types appear in archive and search results:
flowchart LR
subgraph Query["Publication Listing Query"]
WPQuery["WP_Query"]
CoreQuery["core/query block"]
RestQuery["REST API"]
end
subgraph Filter["prc_platform_pub_listing_default_args"]
PostTypes["Included Post Types"]
TaxQuery["Tax Query (visibility)"]
PostParent["post_parent = 0"]
end
subgraph PostTypes["Default Post Types"]
Post["post"]
Feature["feature"]
Quiz["quiz"]
Collections["collections"]
Dataset["dataset (search only)"]
Staff["staff (search only)"]
end
Query --> Filter
Filter --> PostTypes
Notes
- All custom post types support
custom-fieldsfor block editor meta - Most content post types support
revisionsfor version history - The
noteseditor support allows internal notes on posts - Research Teams taxonomy drives permalink structure for most content
- The TDS pattern enables rich taxonomy pages with full editor content