MarkdownMaster CMS includes a server-side page popularity tracking system that records visitor views and calculates weighted scores for each page. This system is designed to be privacy-conscious, with no raw IP addresses or user agent strings stored; only hashes are used.
The system works by:
When a visitor accesses a page, their IP address and User-Agent string are hashed to create a unique identifier that cannot be reverse-engineered to reveal the original information.
All visitor data is stored in a SQLite database (data/cms.sqlite by default) with the following structure:
Views are aggregated daily to reduce database size and improve performance. The rollup process:
daily tableviews tableThe popularity score is calculated using a decayed log-scaled formula:
weighted = Σ views(day) * 2^(-age_days / halfLifeDays)
score = log10(1 + weighted)
Where:
- views(day) = number of human visitors for that day
- age_days = how many days old the data is (from today)
- halfLifeDays = controls how quickly scores decay (default 7 days)
'popularity' => [],
To install this popularity feature, add popularity to your extras config
and then access /install to install the database.
When accessing /install, you will only just see 'OK'.
Check the error log or enable debug mode to check for errors.
The popularity rollup and cleanup jobs run on a cron schedule. You can set up a webcron endpoint by calling:
curl -X GET "https://yoursite.com/cron"
This endpoint is idempotent and safe from double-execution, so it's safe to call via cron or healthchecks.
The popularity score is exposed in the /meta.json endpoint as a popularity field on each page entry.
The value is an int, generally on a score between 0 and 9999.
Example:
{
"pages": [
{
"url": "/pages/home.html",
"path": "pages/home.md",
"meta": {
"title": "Home"
},
"timestamp": 1680000000,
"popularity": 2154
}
]
}
When the popularity feature is disabled or not configured, the popularity field is omitted entirely.
In client-side JavaScript, you can access the popularity score via:
File.getMeta('popularity') // Returns null or a numeric score
// Or from meta.json:
file.popularity // Returns null or a numeric score
A primary purpose of this feature is to integrate with the pagelist directive to provide additional sorting and filtering options.
## Popular Posts
<cms-pagelist type="posts" sort="popularity"></cms-pagelist>
## Really Popular Posts
<cms-pagelist type="posts" sort="popularity" filter-popularity="> 500"></cms-pagelist>
To disable the popularity tracking system entirely:
Remove or comment out the popularity block from your config.php