Àpèjúwe
Turf is a self-hosted, cookieless analytics plugin. No Google Analytics, no
Jetpack, no external network calls Ìtumọ̀ Yorùbá: – everything is measured and stored in your
own WordPress database.
Why Turf
- Cookieless. Visitor deduplication uses a one-way hash of IP + user-agent,
never a cookie and never the raw IP address. - Self-hosted. All data lives in your own database; nothing is sent to any
third party. - Zero configuration. Every public post type and taxonomy is tracked
automatically, including ones you add later.
What it tracks
- Page views (deduplicated and raw), unique visitors, views per visitor, and
average visit duration - Device, browser, operating system, language, and country (via CloudflareÌtumọ̀ Yorùbá: ’s
header when available Ìtumọ̀ Yorùbá: – no GeoIP lookups) - Referrers / traffic sources, UTM campaign parameters, and automatic outbound
link tracking (full destination URL + the page clicked from) - New vs. returning visitors, scroll depth, and reading time
- On-site search terms, including zero-result searches
- Visitor routes (page-to-page transitions), landing pages, and a bounce-rate
proxy Ìtumọ̀ Yorùbá: – all reconstructed from sessions - Cache offload: how much traffic is served by a page cache (SiteGround,
Cloudflare, …) instead of hitting WordPress - 404 hits, comments per period, editorial content activity, per-author stats
- Bots & LLM crawlers (Googlebot, GPTBot, ClaudeBot, …) Ìtumọ̀ Yorùbá: – tracked server-side
and kept separate from human visitor numbers - WooCommerce funnel (views, add to cart, checkout) and form submissions
(Contact Form 7, Gravity Forms) when those plugins are active
The admin pages use native WordPress postboxes: collapsible, draggable,
hideable via Screen Options, and styled by your admin color scheme. The
interface is English and ships with a full Dutch (nl_NL) translation.
Àwọn àwòrán ìbòjú



Ìgbéwọlẹ̀
- Install and activate the plugin.
- ThatÌtumọ̀ Yorùbá: ’s it Ìtumọ̀ Yorùbá: – views start counting immediately for every public post type and taxonomy. Find the reports under the “Statistics” menu in wp-admin.
Optional extras (a visible view counter, click tracking on specific elements, social-share links, importing historical Jetpack/entry-views view counts via the “Statistics > Import” admin page or WP-CLI) are documented in the pluginÌtumọ̀ Yorùbá: ’s README on GitHub.
FAQ
-
Turf sets no cookies and sends no data to any external service. Deduplication
uses a one-way hash of IP + user-agent; the raw IP is never stored. It is
designed to fit a “legitimate interest” basis for first-party, aggregate
analytics Ìtumọ̀ Yorùbá: – but that is not legal advice: check with whoever maintains your
privacy policy. -
What data does Turf collect, and where does it go?
-
Per page view Turf stores, in your own database only: a one-way visitor hash,
timestamp, the page viewed, device type / browser / OS family (parsed from the
user-agent), language, country code (only if Cloudflare provides it), referrer
hostname, UTM parameters, scroll depth, and reading time. Raw event rows are
pruned automatically after 18 months (filterable); aggregate totals are kept.
Nothing is ever transmitted off your server. -
Why are TurfÌtumọ̀ Yorùbá: ’s numbers lower than JetpackÌtumọ̀ Yorùbá: ’s or a raw hit counterÌtumọ̀ Yorùbá: ’s?
-
“Views” is deduplicated: a repeat view of the same page by the same visitor
within 30 minutes doesnÌtumọ̀ Yorùbá: ’t count again (the same default Google Analytics and
Matomo use). The separate “Raw views” number counts every page load, for an
apples-to-apples comparison with hit-counting tools. -
Does it work with page caching?
-
Yes. Tracking runs client-side, so cached pages are still counted. Turf even
reports how much of your traffic is served from cache. -
Where is the country data coming from?
-
From CloudflareÌtumọ̀ Yorùbá: ’s CF-IPCountry request header, if your site is behind
Cloudflare. Turf deliberately does not call any geolocation API Ìtumọ̀ Yorùbá: – that would
mean sending visitor IPs to a third party. Without Cloudflare, country stays
empty unless you hook up your own local database via the turf_visitor_country
filter. -
Does uninstalling remove my statistics?
-
By default, no Ìtumọ̀ Yorùbá: – analytics history is precious, so the data survives an
uninstall/reinstall. To remove everything on uninstall, add
define( ‘TURF_REMOVE_DATA_ON_UNINSTALL’, true ); to wp-config.php (or set
theturf_remove_data_on_uninstalloption to1) before deleting the plugin. -
Where do I suggest a feature or report a bug?
-
On the pluginÌtumọ̀ Yorùbá: ’s GitHub repository: https://github.com/fbloemhof/turf-stats/issues
Àwọn àgbéyẹ̀wò
Kò sí àwọn àgbéyẹ̀wò fún plugin yìí.
Àwọn Olùkópa & Olùgbéejáde
“Turf Stats” jẹ́ ètò ìṣàmúlò orísun ṣíṣí sílẹ̀. Àwọn ènìyàn wọ̀nyí ti ṣe ìkópa sí plugin yìí.
Àwọn OlùkópaṢe o nífẹ̀ẹ́ sí ìdàgbàsókè?
Ṣàwárí koodu, ṣàyẹ̀wò ibi ìpamọ́ SVN, tàbí ṣe àgbékalẹ̀ sí àkọsílẹ̀ ìdàgbàsókè nípasẹ̀ RSS.
Àkọsílẹ̀ àwọn àyípadà
1.23.0
- Custom date ranges: pick any start/end date instead of just the fixed
presets, and save frequently-used ranges by name to jump back to them
later. - CSV export for the overview totals, top pages, top referrers,
device/browser/OS breakdown, search terms, and 404s boxes Ìtumọ̀ Yorùbá: – respects
whatever period (including a custom range) is on screen. - Weekly/monthly email report: a summary of your stats sent to one or more
addresses on a recurring schedule, with a “Send test email now” button to
check formatting/delivery without waiting for the schedule. - Fixed several period-filtered boxes (404s, per-author stats, click and
outbound-link breakdowns, WooCommerce funnel, peak-hours heatmap) silently
including data all the way through “now” instead of stopping at the end
of “Yesterday” or a picked date Ìtumọ̀ Yorùbá: – only affected those two period choices,
not the day/week/month tabs. - Dutch (nl_NL) translation updated for all new strings.
1.22.0
- Track the
utm_contentcampaign parameter (e.g. InstagramÌtumọ̀ Yorùbá: ’s
link_in_bio) alongside the existingutm_source/utm_medium/
utm_campaign, with a matching “Campaign content (UTM)” breakdown box.
1.21.1
- Fixed the “Formulieren” (Forms), “Top search terms” and “Most discussed”
boxes on the Analysis/Statistics pages silently disappearing for any
period other than “All time” Ìtumọ̀ Yorùbá: – a broken date filter made the underlying
query invalid SQL, so it failed silently and the box was dropped.
1.21.0
- New
[turf_stats]shortcode: an at-a-glance table (online now, today,
yesterday, last 7 days, last 28 days) for a sidebar Text/HTML widget or
Shortcode block, withmetric(views/visitors),layout(table/list)
anditemsattributes to customize which rows show. - Fixed a corrupted Dutch (nl_NL) .mo file (duplicate “Online now” source
string made it fail to compile, and the compiled file itself wasnÌtumọ̀ Yorùbá: ’t a
valid sorted .mo) Ìtumọ̀ Yorùbá: – Dutch translations were silently not loading.
1.20.3
- Screen resolution breakdown labels are now English source strings with
Dutch translations in the language file (was accidentally Dutch in code). - Daily chart window math extracted into a shared turf_day_window() helper
so the single-day and 7-day windows no longer duplicate the timezone logic. - Fixed TURF_VERSION (the cache-busting version for all enqueued JS/CSS)
being stuck at 1.19.0 since the 1.20.0 release Ìtumọ̀ Yorùbá: – every asset change since
then was shipped under an unchanged version string.
1.20.2
- Fixed daily bar chart on the Today/Yesterday/fixed-date tabs: it showed
only the anchor day (plus a sliver of the day before under a non-UTC site
timezone) instead of the intended 7-day context window. The chart query
now spans the 7 days ending on the selected day, matching the 7 bars it
renders. Regression from 1.20.0 (date navigation).
1.20.1
- Screen resolution: fall back to viewport innerWidth/innerHeight in the
tracking JS when window.screen reports 0 or is missing (in-app webviews,
fingerprinting-protected browsers) so fewer views land in “unknown”. - Screen resolution breakdown now separates App/REST API views (which never
run the tracking JS and legitimately have no screen size) from real browser
views that failed to report one, instead of lumping both into a single
“unknown” bucket.
1.20.0
- Added date navigation (native date picker, Yesterday tab) with fixed-date sentinel fix.
- Added top-referrers ‘Toon meer’ toggle (shows 10, reveals up to 50).
- Added dashboard widget (online now, todayÌtumọ̀ Yorùbá: ’s views/visitors with % vs yesterday), reusing overview card styling.
- Added review-nudge snooze (random 30-90 days, max 3x then permanent).
- Added device-class label (Phone/Tablet/Desktop) at screen resolution.
- Fixed 90-day chart overflow (gap + horizontal scroll).
- Dutch translations for new strings.
1.19.0
- New “Screen resolution” breakdown box: visitor screen sizes (in CSS
pixels) are recorded with each view. The new database columns are added
automatically on update. - New “Avg. load time” stat box: page load times are measured in the
visitorÌtumọ̀ Yorùbá: ’s browser via the Navigation Timing API and averaged per period. - The “Online now” box gains a live “Currently viewed” list of the pages
current visitors are on, refreshed on the same 20-second poll. - Hourly visitors chart reworked: a fixed 24-hour axis with a dashed
“yesterday” line for direct comparison against the previous day. - Daily views/visitors bars now show their values on the chart, with
density-based label sizing on the 30- and 90-day views. - The Caching box now explains itself when a cache layer is detected but
is serving (almost) none of the tracked page views. - Much faster legacy view-count import: a Jetpack top-posts pre-pass
covers the most-viewed posts in one request, admin-page batches run
concurrently, and the WP-CLI command gains Ìtumọ̀ Yorùbá: –offset/Ìtumọ̀ Yorùbá: –limit flags. - Dutch (nl_NL) translation updated for all new strings.
1.18.1
- Added wordpress.org listing screenshots (Statistics overview, Analysis,
Bots & LLMs) and the corresponding == Screenshots == section. No
functional or tracking changes.
1.18.0
- The GitHub-based update checker is removed entirely (updater.php and its
vendored library) Ìtumọ̀ Yorùbá: – releases now deploy straight to WordPress.org via a
GitHub Action, and updates are handled by wordpress.org like any other
hosted plugin. - Fixed postbox drag-order and collapse/expand state not actually being
saved: the admin pages were missing the nonce fields WordPress coreÌtumọ̀ Yorùbá: ’s own
postbox AJAX handlers look for, so those requests silently failed. Order
and collapsed state now persist correctly per user. - The site-specific “Dorpsapp” companion-app integration is now a generic,
opt-in connector-app mechanism (turf_connector_app_route_patterns/
turf_connector_app_label filters) Ìtumọ̀ Yorùbá: – no behavior change unless you were
using the oldturf_dorpsapp_route_patternsfilter, which is renamed. - Added a GitHub issues link (bug reports / feature suggestions) to the FAQ.
- The legacy view-count import (Jetpack Stats / the old entry-views plugin) is
now also available as a “Statistics > Import” admin page, alongside the
existingwp turf-stats import-legacy-viewsWP-CLI command Ìtumọ̀ Yorùbá: – same import,
run in small AJAX batches with a progress bar instead of the command line.
1.17.2
- Fixed a WordPress.org submission error: the Plugin URI and Author URI
headers pointed at the same URL. Author URI now points at the authorÌtumọ̀ Yorùbá: ’s
GitHub profile instead of the plugin repo.
1.17.1
- Cleared the remaining WordPress.org Plugin Check warnings: dropped the
now-redundant load_plugin_textdomain() call (translations for wp.org-hosted
plugins load automatically since WP 4.6) and annotated the opt-in REST debug
logger. No functional or tracking changes.
1.17.0
- WordPress.org compliance release: readme.txt, uninstall.php with opt-in data
removal, direct-access guards on all files, and the GitHub update checker is
no longer part of the WordPress.org build (updates come from wordpress.org).
1.16.1
- Long lists are now collapsed before first paint (CSS), eliminating the
load-time jump introduced in 1.16.0.
1.16.0
- Cache offload insight (served-from-cache % with layer detection).
- Landing pages report with per-landing bounce rate.
- Blocks with no data for the selected period are hidden entirely.
- All lists use one in-place Show more / Show less toggle; server-side
pagination removed.
1.15.0
- Bilingual: English source strings with a bundled Dutch (nl_NL) translation.
1.14.0
- Raw (non-deduplicated) view counting, views per visitor, average visit
duration, an hourly visitors chart for “Today”, and full-URL outbound link
tracking including the source page.
Earlier
- See https://github.com/fbloemhof/turf-stats/releases for the full history.
