| 开发者 | brokensmile.2103 |
|---|---|
| 更新时间 | 2026年10月4日 15:55 |
| PHP版本: | 7.4 及以上 |
| WordPress版本: | 7.1 |
| 版权: | GPLv2 or later |
| 版权网址: | 版权信息 |
_init_view_count, _init_view_day_count, etc.[init_view_count] and [init_view_list] shortcodes[init_view_ranking] shortcode with tabbed ranking by time range[init_view_list] via the page attribute/wp-content/plugins/init-view-count/[init_view_count] or [init_view_list] in your content= Can I customize the layout of the list? =\
Yes. Use the template attribute in [init_view_list] (e.g. template="grid"), and override the corresponding file in your theme like WooCommerce templates.
= Does it work with custom post types? =\
Yes. Just set post_type="your_custom_type" in the shortcode or REST query.
= How does it avoid duplicate views? =\
Init View Count uses both time delay and scroll detection via JavaScript, and stores viewed post IDs in either sessionStorage or localStorage (your choice).
= Is the view count updated immediately? =\
Yes, by default. When the scroll+delay conditions are met, the count is sent via REST API and saved with a single atomic database update. If you enable Reduce view count cache refreshes, views are still written to the database immediately, but the numbers displayed on your site may lag behind by up to the configured interval (see below).
= What meta key is used to store views? =\
By default:
_init_view_count (total)_init_view_day_count_init_view_week_count_init_view_month_count\
These keys can be changed via the init_plugin_suite_view_count_meta_key filter.
Trending scores are calculated separately and stored in a transient.
= Can I display view counts in my template manually? =\
Yes. Use get_post_meta($post_id, '_init_view_count', true) or similar keys. Or use [init_view_count] shortcode in post content./top) are cached using transients.
= Can I use it in block editor / Gutenberg? =\
Yes — since version 2.0.0 there are 3 native blocks (search "View Count", "Popular Posts List", "View Ranking" in the block inserter, under the "Init View Count" category), each with its own settings panel and live preview. You can still use the classic Shortcode block with [init_view_count] / [init_view_list] / [init_view_ranking] if you prefer.
= What is Abilities API support and do I need it? =\
Since version 2.0.0, on WordPress 6.9+ the plugin registers two read-only Abilities (init-view-count/get-post-views and init-view-count/get-top-posts) via the core Abilities API, so AI agents and automation tools can discover and query view-count data in a standardized way. This is entirely optional and has no effect on sites without the Abilities API (WordPress below 6.9) or on how the plugin otherwise works — no view/increment/reset ability is exposed.
= Does it track bots? =\
No. Since counting only happens after scroll and delay via JavaScript, bots like Googlebot are naturally excluded.
= Can I sort posts by views in WP_Query? =\
Yes. Use 'meta_key' => '_init_view_count' and 'orderby' => 'meta_value_num' in your WP_Query args.
Yes. You can enable batch view tracking in the plugin settings. Instead of sending one request per view, views will be stored in the browser and sent in a group once the threshold is reached.
Only if your site uses a persistent object cache (Redis, Memcached, etc.) and gets a lot of traffic. By default, each counted view clears the cached metadata of that post, so a popular post has to reload all of its metadata from the database again and again. With this option on, each post's cache is refreshed at most once per interval (60 seconds by default, 10–600 allowed). Every view is still written to the database right away and nothing is lost — only displayed numbers (shortcodes, blocks, rankings, Trending, the number shown after counting) may be slightly behind. A post that stops receiving views may keep showing a slightly lower number until it gets another view, is updated, or the daily reset runs (when daily views are enabled). Without a persistent object cache the option has no effect, and the settings page tells you so.
Only on busy sites with Trending enabled. The Traffic Shape Learner (which teaches Trending your site's hourly and weekday rhythm) updates a database option on every view request. With sampling on, it records only 1 in every N requests (10 by default, 2–100 allowed) and counts each sample N times, so it writes about N times less often while the expected numbers stay the same. On low-traffic sites the learned pattern becomes noisier, so leave it off there. Post view counts are never sampled.
A little. It reads a transient on every view request and writes it back every time a view is counted. With a persistent object cache (Redis, Memcached) that happens in memory. Without one, transients live in the wp_options table, so each counted view adds up to two extra database writes. On busy sites without a persistent object cache, only enable it if you really need it.
It's optional and off by default. Enabling it makes the /count endpoint reject requests that don't carry a valid WordPress REST nonce, which helps block fake POST requests sent directly to the endpoint. However, WordPress nonces expire after roughly 12-24 hours. If your site uses full-page caching with a long TTL, cached pages will keep serving an old nonce and view counting will quietly stop working on those pages until the cache refreshes. Leave it off on sites with long-lived page caching, or make sure the cache is purged/refreshed regularly. The /top endpoint is unaffected either way, since it's read-only and public by design.
wp_cache_delete( $post_id, 'post_meta' )) — not just the view counters, but every meta value of the post. On sites with a persistent object cache, a popular post therefore had its cache wiped dozens of times per minute, and every page render right after had to reload all of the post's metadata from the database. With this option on, each post's meta cache is refreshed at most once per interval (a per-post lock via wp_cache_add(), atomic on Redis/Memcached). Views are still written to the database immediately with the same atomic UPDATE, so no view is ever lost or double-counted; only displayed numbers (shortcodes, blocks, rankings, Trending and the number returned after counting) may lag behind by up to the interval. A post that stops receiving views catches up on its next view, when it is updated, or at the daily reset (when daily views are enabled). The option only takes effect when a persistent object cache is active — on sites without one, cached metadata only lives for a single request, behavior stays exactly as before, and the settings page shows a notice explaining thisinit_plugin_suite_view_count_meta_flush_interval to adjust the refresh interval per site (return 0 to refresh after every view)get_option() + update_option() on every view request — one extra database write per view, on every site. With sampling on, only 1 in N requests is recorded and each sample counts N times, so writes drop by about N times while the expected hourly bins and daily total stay the same (the daily minimum threshold and the hour/weekday EMA need no change). It also reduces concurrent requests overwriting each other's update of the same option. In a 200,000-request simulation at N = 10, writes went from 200,000 to ~20,000 and the recorded total was within 0.4% of the real one. On low-traffic sites the learned pattern becomes noisier, which the settings page explains. Post view counts are never sampled. Filterable via the new init_plugin_suite_view_count_shape_sample_rate filter (return 1 to record every request)init_plugin_suite_view_count_get_meta_flush_interval() and init_plugin_suite_view_count_maybe_flush_meta_cache() in includes/utils.php, and init_plugin_suite_view_count_get_shape_sample_rate() in includes/traffic-shape.php. init_plugin_suite_view_count_flush_meta_cache() is unchanged and still clears the cache unconditionally; the daily reset keeps using it, so rollover always refreshes the cache of affected postswp_options writes per counted viewupdate_post_meta() (counts have been saved with a single atomic SQL update since 2.0.2); added FAQ entries for the two new options and for the performance cost of Strict IP check; documented the two new filtersreadme.txt — the Block Editor and Abilities API FAQ entries said "since version 1.23" (both shipped in 2.0.0); [init_view_count] was described as only working inside a post loop and was missing its id attribute; [init_view_list] listed a default number of 5 (it is 10); [init_view_ranking] was missing its post_type attribute and the yesterday/last_week/last_month tabs; GET /top listed post as the default post type (it is post and page), was missing the yesterday/last_week/last_month/trending ranges and the 100-item cap; the init_plugin_suite_view_count_trending_component_weights filter listed only 4 of its 9 weights and was rendered on a single linereadme.txt; the full history is available at the link belowinit-view-count.pot with WP-CLI; new strings translated in init-view-count-vi.po/.moWordPress-Extra) with zero errors and warningsinit_plugin_suite_view_count_shape_reset admin-post action (clears learned Traffic Shape data) had no capability check and no nonce, so any logged-in user (even a Subscriber), or a CSRF link, could wipe the learned data. It now requires manage_options and a valid nonce. A Reset traffic shape data button (with nonce) has been added to Settings → Init View Count. Custom links must now be built with wp_nonce_url( admin_url( 'admin-post.php?action=init_plugin_suite_view_count_shape_reset' ), 'init_plugin_suite_view_count_shape_reset' )GET /top now only accepts post types that exist and are publicly viewable (is_post_type_viewable()), so the public endpoint can no longer expose titles/excerpts of internal post types such as wp_block. The init_plugin_suite_view_count_top_post_types filter still runs afterwards, so developers can explicitly add other types. number is capped at 100 (filterable via the new init_plugin_suite_view_count_api_top_max_number filter). An array passed as terms no longer causes a PHP fatal error[init_view_ranking] front-end script now builds items with DOM APIs (textContent) instead of injecting API strings into innerHTML, and only allows http(s) links/imageswp_date(). The $now value passed to the existing hooks/filters is unchangeddaily recurrence is a fixed 24h and used to drift to 23:01 or 01:01). Sites without DST are never touchedtrending_last_calculation values stored in local time are handled safely on upgradeterm_taxonomy_id values to get_term() as if they were term IDs. The two are not always equal (split/merged terms, migrated sites), so "hot" boosts could be attributed to the wrong category/tag. The query now returns term IDs and taxonomies directly[init_view_count time="true"] showed "Posted 7 hours ago" for a just-published post on GMT+7 sites (GMT timestamp compared against a local timestamp)POST /count request containing the same post ID several times (e.g. [5,5,5]) incremented that post several times. Duplicate IDs in one request are now ignored[init_view_ranking] only initialised the first ranking block on a page; additional rankings stayed on the loading skeleton forever. Every ranking block is now initialised, and each keeps its own post_type/wp-json/ when the tracking script was not on the page (archive pages, the Dashboard widget), which broke on sites installed in a subdirectory or without pretty permalinks. The correct REST URL is now always providedlocalStorage/sessionStorage (Safari private mode, strict privacy settings). Storage access is now guarded with an in-page fallbackclassName values with multiple classes (e.g. foo bar) were merged into foobar; [init_view_count class="..."] now accepts multiple classes tooTop [2026]) broke the generated shortcode. Blocks now call the shortcode callback directly with an attribute array (core pre_do_shortcode_tag/do_shortcode_tag filters still apply)get_the_ID(), so a theme/plugin that runs a secondary query before wp_head without resetting it can no longer make views count toward the wrong postinit_plugin_suite_view_count_format_thousands() could output 1000.0 K (for 999,950) and 2.0 K; it now outputs 1 M and 2 KGET /top, as the setting describesPOST /count now increments all counters of a post (total/day/week/month) with a single atomic UPDATE instead of one query per counter — 2 queries per view instead of 5 in the common case. First-view inserts and stale-cache situations are still handled atomicallyGET /top primes featured-image caches in one query; its cache key ignores parameter order and cache-buster parameters (_, no_cache); [init_view_list] also primes featured imagesdefer strategy; fetch uses keepalive so a view is still sent if the visitor leaves right as it qualifiespostId (Query Loop, FSE templates) when Post ID is 0init_plugin_suite_view_count_ip_headers to restrict which headers are trusted for Strict IP check (e.g. only REMOTE_ADDR on servers not behind a proxy/CDN)/top results, which the previous uninstall could not find), and runs on every site of a multisite networkinit-view-count.pot with WP-CLI; new strings translated in init-view-count-vi.po/.moWordPress-Extra) with zero errors and warnings_init_view_day_count directly would show it growing forever instead of rolling over into _init_view_day_yesterday. All reads of the day/week/month enable options now consistently default to enabled, matching the REST counting logic and the settings page's default-checked checkboxes0 did not actually count views immediately — it silently fell back to the default (15000ms) or, depending on the browser, sometimes did not count at all. Same issue affected "Scroll percent required" set to 0. Root cause was a value || fallback pattern in the front-end script, which treats a valid 0 as falsy and always substitutes the default. Both options are now validated on save, enforced again at output time (so sites that already had 0 stored take effect without needing to re-save), and parsed correctly in the front-end scriptscroll event handler, and no scroll event fires when there is nothing to scroll. The script now also evaluates the scroll condition once immediately after the page settles, in addition to on scroll0 is intentionally disallowed for both: a 0ms delay risks counting views before the page has actually rendered, and a 0% scroll requirement would silently disable the scroll check entirelyinit_plugin_suite_view_count_reset_counts — rolls today's/this week's/this month's view counts into yesterday/last-week/last-month and clears the counters, across every publicly-registered post type, no configuration needed) used to loop get_post_meta() + update_post_meta() + delete_post_meta() per post per counter, which on sites with many posts could mean tens of thousands of individual DB queries in a single cron run. It now performs the same rollover in batched, direct SQL (500 posts per query by default, filterable via init_plugin_suite_view_count_reset_batch_size), cutting query count from O(number of posts) to O(number of batches), then flushes the object cache for affected posts in one pass — using the object cache's batch-delete method when the active cache backend supports it (WordPress core does, since 6.0), and falling back to individual cache-delete calls otherwise for compatibility with third-party object cache drop-ins (Redis, Memcached, etc.) that may not implement it. Behavior is unchanged: every eligible post still ends up with a "previous period" value (0 if it had no views), preserving correct results in GET /top?range=yesterday|last_week|last_month; verified against the previous per-post logic across 1,000+ randomized scenarios before releaseinit_plugin_suite_view_count_atomic_increment(), init_plugin_suite_view_count_flush_meta_cache(), IP-detection helpers, the K/M/B number formatter, and the new integer-clamping helper) out of rest-api.php and shortcodes.php into a new includes/utils.php, loaded first. No behavior change, purely a code-organization cleanupextract() in the internal template-rendering helper with an explicit variable assignment for WPCS compliance (WordPress.PHP.DontExtract); the helper is only ever called with a single fixed key, so behavior is unchangedRequires at least is now WordPress 6.9. This major version bump reflects two significant new features added in this release — Abilities API support and native Block Editor support (see below)init-view-count category so AI agents and automation tools can discover and query view-count data through the standardized wp_register_ability() registry, without needing to know the plugin's REST routes:init-view-count/get-post-views — returns the tracked view count for a single post (total/day/week/month)init-view-count/get-top-posts — returns a ranked list of the most viewed posts (wraps the exact same logic as GET /top and the [init_view_ranking] shortcode, so results always match)render.php, via the render field in block.json) that builds the same shortcode tag and calls do_shortcode(), so there is no duplicated display logic and output always matches the shortcode. The editor script is plain vanilla JavaScript (no build step, no JSX) using ServerSideRender for a live preview directly in the editorTested up to: 7.1
View full changelog (all versions): Init View Count – Changelog