| 开发者 | brokensmile.2103 |
|---|---|
| 更新时间 | 2026年9月26日 11:41 |
| 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. When the scroll+delay conditions are met, the count is updated via REST API and saved using update_post_meta().
= 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 1.23 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 1.23, 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.
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.
init_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.1GET /top (and by extension the [init_view_ranking] shortcode, which consumes it) and the hourly Trending Engine calculation could show a sticky post at the top of the list regardless of its actual view count, since the underlying WP_Query calls were missing ignore_sticky_posts. All ranking queries now explicitly ignore sticky posts, consistent with [init_view_list], which already did this correctlyscript.js) is now throttled with requestAnimationFrame instead of running its calculation on every single scroll event, and is automatically removed once the scroll threshold is reached — reduces main-thread work on long pages and low-end mobile devices. The listener is also registered as passive to avoid blocking scroll rendering. Also fixed a theoretical division-by-zero edge case when a page's content is shorter than the viewportPOST /count requires a valid X-WP-Nonce header and rejects the request with 403 otherwise, helping block direct spam POSTs to the endpoint that skip loading the page firstGET /top is intentionally excluded, since it's a read-only, public-by-design endpointInvalid post ID., Not enabled for view counting.) plus all new strings from this release to languages/init-view-count.pot, with ready-made Vietnamese translations in languages/init-view-count-vi.po / .mo/count REST endpoint:total, day, week, month) are now incremented with a direct, atomic SQL UPDATE ... SET meta_value = meta_value + 1 instead of a read-then-write get_post_meta() + update_post_meta() pair, removing a race condition that could drop views under concurrent trafficcached value + 1) instead of re-querying the database after the write, saving a query per counted keyget_option()/update_option() call on shutdown, instead of once per counted post — meaningful reduction in option writes on sites using batch view trackingphpcs:ignore justifications, no behavior change to existing filters/actions)init_plugin_suite_view_count_enable_day → default = 1init_plugin_suite_view_count_enable_week → default = 1init_plugin_suite_view_count_enable_month → default = 1_init_view_day_yesterday, _init_view_week_last, _init_view_month_last[init_view_ranking]:yesterday, last_week, last_monthtotal,day,week,month) for compatibilityinit_plugin_suite_view_count_top):range parameter extended with yesterday, last_week, last_monthinit_plugin_suite_view_count_meta_key for extensibilityinit_plugin_suite_view_count_site_traffic_shape provides current hour/day shape arraysinit_plugin_suite_view_count_shape_collect_enabled allows enabling/disabling collectioninit_plugin_suite_view_count_shape_reset to clear all learned shape dataviews_day_used and fallback flags for transparencyinit_plugin_suite_view_count_trending_debug_row available for developers to log detailed trending rowsinit_plugin_suite_view_count_trending_component_weights, init_plugin_suite_view_count_meta_key)init_plugin_suite_view_count_trending_post_types – limit/override post types (e.g., only manga)init_plugin_suite_view_count_trending_component_weights – adjust weights for velocity, engagement, freshness, momentumattachment, safe fallback when emptyinit_plugin_suite_view_count_top_post_types filter to allow overriding post_type in top view REST API routemanga, article, etc.)[init_view_count] now supports id="..." attribute to display the view count of any post (not just the current one)id is omitted, the current post will be used as before[init_view_ranking] now supports post_type="..." to filter rankings by custom post typeranking.js updated to pass post_type to REST API and cache results per tab and typeinit_plugin_suite_view_count_human_time_diff() in favor of core human_time_diff()[init_view_count] shortcode to use native human_time_diff() for publishing time displayhuman_time_diff() instead of removed custom functionicon="true" attribute to [init_view_count] shortcode to display inline SVG before the view countschema="true" attribute to [init_view_count] to output Schema.org microdata (InteractionCounter)class="custom-class" attribute to allow injecting custom CSS classes into the shortcode wrapperinit_plugin_suite_view_count_default_shortcode allows developers to override default auto-insert outputinit_plugin_suite_view_count_auto_insert_enabled gives control over whether auto-insert is active per contextmatch expressions with backwards-compatible logic using array maps and switchesinit_plugin_suite_view_count_meta_key and template behavior[init_view_list], and [init_view_count] shortcodesinit-shortcode-builder.js with full shortcode configuration UI[init_view_list], [init_view_ranking], and [init_view_count] shortcodesInitViewCountShortcodeBuilder.i18nrange=trending support added to /top REST endpoint with built-in sorting and pagination[init_view_list range="trending"] now fetches trending posts[init_view_ranking] shortcode to display tabbed ranking UI by day/week/month/all-timestyle.cssstyle.css earlier to avoid being printed in the footerinit_plugin_suite_view_count_meta_key consistently across REST API, shortcodes, and background taskspage parameter to /top REST endpoint for paginationpage attribute to [init_view_list] shortcode for paginated lists