*/ public static function defaults(): array { return [ // Counting 'tracking_mode' => 'php', 'post_types' => [ 'post', 'page' ], 'exclude_logged_in' => false, 'exclude_roles' => [ 'administrator', 'editor' ], 'session_interval' => 30, // Stored as minutes (default 30 min) 'trust_proxy_headers' => false, 'count_bots' => false, // Display 'views_label' => 'views', 'display_post_types' => [ 'post' ], 'default_style' => 1, 'default_variant' => 'outline', 'auto_insert' => 'none', // Data 'data_retention_days' => 90, 'delete_data_on_uninstall' => false, 'geo_tracking' => false, ]; } public function set_defaults(): void { if ( ! get_option( self::OPTION_KEY ) ) { add_option( self::OPTION_KEY, self::defaults(), '', false ); } } public function render(): void { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You do not have permission.', 'pulseviews' ) ); } $saved = false; $error = ''; if ( isset( $_POST['pulseviews_save'] ) ) { if ( ! check_admin_referer( self::NONCE ) ) { $error = 'Security check failed.'; } else { $this->save_settings(); $saved = true; } } $s = $this->get_settings(); $post_types = get_post_types( [ 'public' => true ], 'objects' ); $all_roles = wp_roles()->roles; $active_tab = sanitize_key( wp_unslash( $_GET['tab'] ?? 'counting' ) ); $tabs = [ 'counting' => 'Counting', 'display' => 'Display', 'other' => 'Other', ]; ?>

Settings

Configure PulseViews tracking, display, and privacy options.

✓ Settings saved successfully.
✕
$name ) : $url = add_query_arg( [ 'page' => 'pulseviews-settings', 'tab' => $slug ], admin_url( 'admin.php' ) ); $cls = $active_tab === $slug ? ' active' : ''; ?>
⚡
Tracking Targets
What gets counted
Tracking mode
PHP tracks on server render. JS tracks async (cache-friendly). Both uses PHP with JS fallback.
Track post types
Select which post types should have their views counted.
Session interval (minutes)
Minimum minutes between counting repeat views from the same visitor. Set to 0 to count every single page load/refresh.
Count bot traffic
Bot views are always stored but excluded from counts by default. Enable to include them.
Trust proxy headers
Enable if behind Cloudflare, Nginx proxy, or a load balancer to get the real visitor IP.
🚫
Exclusions
Who should not be counted
Exclude logged-in users
Skip counting views from any logged-in WordPress user.
Exclude roles
Views from these user roles will not be counted even if "exclude logged-in" is off.
$role_data ) : ?>
🎨
Badge Appearance
How the view count looks on your site
View count label
The word shown after the number. Use anything — "views", "readers", "hits", "visitors", "people read this".
Display style
Visual style of the view badge. Pill = rounded. Block = bold counter. Inline = plain text. Compact = minimal badge for cards.
'💊 Pill', 2 => '⬛ Block', 3 => '— Inline', 4 => '▪ Compact' ]; foreach ( $styles as $num => $lbl ) : $sel = ( (int) ( $s['default_style'] ?? 1 ) === $num ) ? ' sel' : ''; ?>
Colour variant
Outline uses the theme text colour. Filled adds a solid black/white background. Accent uses your brand colour via the --pv-accent CSS variable.
📍
Placement
Where the badge appears on your site
Show badge on
Which post types display the view badge. All tracked types are still counted — this only controls where the badge is shown. Pages are counted but hidden by default.
Auto-insert position
Automatically inject the badge into post content without a shortcode.
📎
Shortcode Reference
Manual placement options
'Current post, default style', '[pulseviews style="1" variant="filled"]'=> 'Pill — filled variant', '[pulseviews style="1" variant="accent"]'=> 'Pill — accent colour', '[pulseviews style="2"]' => 'Bold block counter', '[pulseviews style="3"]' => 'Inline text', '[pulseviews style="4"]' => 'Compact badge', '[pulseviews label="readers"]' => 'Custom label', '[pulseviews period="week"]' => 'Views this week only', '[pulseviews id="42"]' => 'Specific post by ID', ]; foreach ( $refs as $code => $desc ) : ?>
🗄
Data & Privacy
Retention and cleanup
Geographic tracking
Sends visitor IPs to ip-api.com to resolve country. Disabled by default — you must opt in. Not needed if you use Cloudflare. See the plugin readme External Services section for full disclosure.
Raw data retention
Raw view events older than this are automatically pruned. Aggregated totals are kept permanently.
⚠️
Danger Zone
Irreversible actions
Delete all data on uninstall
When enabled, deleting the plugin will permanently drop all PulseViews tables and options. Cannot be undone.
*/ private function get_settings(): array { return wp_parse_args( (array) get_option( self::OPTION_KEY, [] ), self::defaults() ); } }