Post Views Counter persists view tracking data in four custom database tables. The core wp_post_views table is available in both Lite and Pro versions, providing the foundation for post and page view counting. Three additional tables extend tracking capabilities in Pro for taxonomy terms, traffic sources, and custom object types.

All table names use the WordPress configurable prefix (wp_ by default), which adapts to your installation’s $table_prefix setting in wp-config.php. Tables are created automatically during plugin activation through WordPress dbDelta() function calls.

Architecture

The database layer serves as the persistence foundation for the plugin’s tracking and reporting features. View counts flow from the counter mechanisms—PHP Mode, JavaScript Mode, REST API Mode, and Fast AJAX—into the wp_post_views table.

Counter Modes (PHP Mode, JavaScript Mode, REST API Mode, Fast AJAX)
        │
        ▼
wp_post_views (post/page views — Lite + Pro)
        │
<!-- pro -->
        ├──► wp_post_views_other (custom objects — Pro)
        ├──► wp_post_views_sources (traffic sources — Pro)
        └──► wp_post_views_terms (taxonomy views — Pro)
<!-- /pro -->

Query operations are distributed across approximately 21 source files, with the primary query sites located in includes/class-counter.php, includes/functions.php, and includes/class-import.php. All database queries use $wpdb->prepare() for parameterized statements, preventing SQL injection vulnerabilities.

API Reference

wp_post_views

The primary table storing post and page view counts. This table is the foundation for all view tracking in both Lite and Pro versions.

Column Type Nullable Default
id bigint NO
type tinyint(1) NO
period varchar(8) NO
count bigint NO

Column Semantics:

  • id — The post or object identifier (correlates with WordPress post IDs)
  • type — Object type discriminator identifying the content type being tracked
  • period — Time period identifier for aggregated counts (e.g., total, 2026-03, 2026-W09)
  • count — Cumulative view count for the specific id/type/period combination

Keys:

  • PRIMARY KEY: type, period, id — Optimized for lookups by content type and time period
  • UNIQUE INDEX id_type_period_count: id, type, period, count — Ensures uniqueness and supports reverse lookups
  • INDEX type_period_count: type, period, count — Optimizes aggregate queries filtering by type and period

The composite primary key design enables efficient retrieval of both total views and time-bounded views (daily, weekly, monthly) without requiring separate queries for each period type.


wp_post_views_other

Stores view counts for custom object types beyond standard posts and pages. This table enables tracking of arbitrary content types configured via Post Views > Counting > Tracking Targets.

Column Type Nullable Default
id BIGINT(20) AI NO
type TINYINT(1) NO
subtype VARCHAR(?) NO

Column Semantics:

  • id — Auto-incrementing unique identifier for the tracked object
  • type — Primary object type classification
  • subtype — Secondary classification enabling granular categorization within a type

Keys:

  • PRIMARY KEY: id — Auto-increment primary key for unique identification
  • UNIQUE INDEX type_subtype: type, subtype — Ensures uniqueness of type/subtype combinations

wp_post_views_sources

Tracks traffic source attribution for view counts, enabling analytics on visitor origins. This supports the reporting and analytics features accessible through the Reports interface.

Column Type Nullable Default
id BIGINT(20) NO
type TINYINT(1) NO
period VARCHAR(8) NO
count BIGINT(20) NO
content TINYINT(1) NO

Column Semantics:

  • id — Related object identifier (correlates with content being viewed)
  • type — Source type classification (e.g., search, social, direct, referral)
  • period — Time period for aggregation (matches period format in wp_post_views)
  • count — View count attributed to this source for the specified period
  • content — Content type discriminator for multi-type source tracking

Keys:

  • PRIMARY KEY: type, period, id, content — Composite key for efficient source-content-period lookups
  • UNIQUE INDEX id_type_period_count: id, type, period, count, content — Ensures uniqueness across all dimensions
  • INDEX type_period_count: type, period, count, content — Optimizes source-based aggregate queries

wp_post_views_terms

Stores taxonomy term view data, enabling tracking of category, tag, and custom taxonomy archive views. This supports the taxonomy tracking feature configurable at Post Views > Counting > Tracking Targets.

Column Type Nullable Default
id INT(10) AI NO
name VARCHAR(200) NO
slug VARCHAR(200) NO
parent INT(10) NO
group VARCHAR(8) NO
uid INT(10) NO

Column Semantics:

  • id — Auto-incrementing term record identifier
  • name — Term name (human-readable label)
  • slug — URL-safe term slug for permalink structures
  • parent — Parent term ID for hierarchical taxonomies (categories)
  • group — Grouping identifier for taxonomy type categorization
  • uid — Unique identifier for correlation with view count data

Keys:

  • PRIMARY KEY: id — Auto-increment primary key for unique term identification

Code Examples

Retrieving Post Views via Template Functions

The preferred method for accessing view data is through the plugin’s template functions, which handle database queries internally:

// Get total views for a specific post
$post_id = 123;
$total_views = pvc_get_post_views( $post_id );

// Get views for a specific time period
$monthly_views = pvc_get_post_views( $post_id, '2026-03' );

// Get views for multiple posts
$post_ids = array( 123, 456, 789 );
$views = pvc_get_views( 'post', $post_ids );

Direct Database Queries

For custom integrations requiring direct database access, use $wpdb with prepared statements:

global $wpdb;

$table = $wpdb->prefix . 'post_views';

// Get top viewed posts in a specific year
$top_posts = $wpdb->get_results(
    $wpdb->prepare(
        "SELECT id, SUM(count) as views 
         FROM {$table} 
         WHERE type = 0 
         AND period LIKE %s 
         GROUP BY id 
         ORDER BY views DESC 
         LIMIT 10",
        '2026-%'
    )
);

// Get views for a specific period range
$period_views = $wpdb->get_var(
    $wpdb->prepare(
        "SELECT SUM(count) FROM {$table} 
         WHERE id = %d 
         AND period BETWEEN %s AND %s",
        $post_id,
        '2026-01',
        '2026-12'
    )
);

Querying Pro Tables

Pro tables follow the same $wpdb->prepare() pattern for custom queries:

global $wpdb;

// Query term views from wp_post_views_terms
$term_table = $wpdb->prefix . 'post_views_terms';
$terms = $wpdb->get_results(
    $wpdb->prepare(
        "SELECT * FROM {$term_table} WHERE `group` = %s",
        'category'
    )
);

// Query source attribution from wp_post_views_sources
$sources_table = $wpdb->prefix . 'post_views_sources';
$sources = $wpdb->get_results(
    $wpdb->prepare(
        "SELECT type, SUM(count) as total 
         FROM {$sources_table} 
         WHERE id = %d 
         GROUP BY type
         ORDER BY total DESC",
        $post_id
    )
);

// Query custom objects from wp_post_views_other
$other_table = $wpdb->prefix . 'post_views_other';
$custom_objects = $wpdb->get_results(
    $wpdb->prepare(
        "SELECT * FROM {$other_table} WHERE type = %d",
        $custom_type_id
    )
);

Integration with Multilingual Plugins

Pro includes specialized query handling for multilingual integrations:

// Polylang integration queries (includes/integrations/polylang.php)
// Uses $wpdb->prepare() for language-aware view queries

// WPML integration queries (includes/integrations/wpml.php)
// Uses $wpdb->prepare() for translation-aware view queries