JS Stats ← Home

Install & self-hosting guide

JS Stats runs on ordinary cPanel shared hosting. Upload the files, enter your database details, add one script tag. No VPS, no Docker, no Node.js, no build step — about 15 minutes.

Requirements Install Cron jobs Optional extras Upgrading Troubleshooting FAQ

Requirements

PHP 7.4+8.x recommended
MySQL / MariaDBany recent version
pdo_mysql + mbstringenabled by default
~20 MB diskplus your data

That is the whole list. No shell access, no Composer, no Node.js, no Docker, no cron access strictly required (the crons add retention, rollups, alerts and uptime, but the analytics work without them).

Install, step by step

1

Check the requirements

PHP 7.4 or newer (8.x recommended) with the pdo_mysql and mbstring extensions, and a MySQL or MariaDB database. Every mainstream cPanel plan has all of this by default. You do not need shell access, Composer, Node.js, Docker or a VPS.

2

Create a database

In cPanel open MySQL Databases, create a database and a user, then add the user to the database with ALL PRIVILEGES. Note the database name, username and password.

3

Upload the files

Extract the archive and upload it to your account. Point the domain or subdomain document root at the public/ folder. If your host will not let you move the document root, upload everything into public_html instead — the bundled .htaccess handles that layout too.

4

Enter your database details

Copy config/config.example.php to config/config.php and fill in the db block, then set app_url to the address you will use. Keep config.php out of version control: it holds your credentials and your ip_salt.

5

Open the installer

Visit your domain in a browser. On first run the schema is imported automatically and you are asked to create the first admin account. The installer disables itself immediately afterwards and will simply redirect to the login page from then on.

6

Add the tracking snippet

Add a site in the dashboard, open its Tracking code, and paste the one-line script tag into your site before </body>. Data appears in real time — open Real-time and load a page to confirm. WordPress users can install the bundled plugin from wp-plugin/ instead.

7

Schedule the cron jobs

In cPanel add the crons you need. Daily is fine for prune (data retention), rollup (keeps large date ranges fast) and lifecycle; every 5 minutes suits alerts and uptime. Each is a plain CLI script, for example: php /home/USER/js-stats/cron/rollup.php

Cron jobs

All optional, all plain CLI scripts. Add them in cPanel → Cron Jobs, replacing the path with your own.

# daily php /home/USER/js-stats/cron/rollup.php # keeps big date ranges fast php /home/USER/js-stats/cron/prune.php # applies your data-retention setting php /home/USER/js-stats/cron/lifecycle.php # trial/grace/expiry (only if billing is on) php /home/USER/js-stats/cron/send_reports.php # scheduled email digests # every 5 minutes php /home/USER/js-stats/cron/alerts.php # traffic spike / drop alerts php /home/USER/js-stats/cron/uptime.php # uptime monitoring

Optional extras

Country data without Cloudflare. Import a free IPv4→country CSV once with php cron/import_geoip.php ranges.csv. Countries are resolved and stored per hit as it arrives, so importing only affects new traffic — do it early. Behind Cloudflare the CF-IPCountry header is used automatically and no import is needed.

Push-based real-time. The Real-time view polls every 15 seconds out of the box. If your host allows a Node process, the self-contained server in realtime-node/ upgrades that to websockets; if it is absent the app falls back to polling on its own.

WordPress. Install the plugin in wp-plugin/ and paste your tracking ID — it injects the snippet for you.

Upgrading

Upload the new files over the old ones, keeping your config/config.php. Schema changes apply themselves on the next dashboard load, so there is no migration command. Hard-refresh once afterwards if the styling looks stale.

Troubleshooting

The page is blank, or I get a 500

Almost always the database block in config/config.php. Check the name, user and password, and that the user was added to the database with full privileges. Your host's error log will name the exact cause.

I see the PHP source instead of the page

PHP is not executing for that directory — usually the document root points somewhere unexpected, or the file was uploaded with the wrong extension. Confirm the domain's document root is the public/ folder.

Links like /dashboard give a 404

Clean URLs need Apache's mod_rewrite and the bundled .htaccess. Make sure .htaccess actually uploaded — many FTP clients hide dotfiles by default.

No data is showing up

Check the snippet is on the page and the tracking ID matches the site. Headless browsers and bots are filtered out by design, so test with a normal browser. If you set enforce_site_domain, confirm the site's domain field matches where the snippet runs.

FAQ

Do I need a VPS or Docker?

No. That is the main reason this exists. It is plain PHP and MySQL, deployed by uploading files, so it runs on the same $2–5/month shared hosting most sites already use. Most privacy-analytics tools require Docker or a VPS.

Do I need a cookie consent banner?

In the default cookieless mode the tracker stores nothing in the browser — a visitor is identified by a daily-rotating server-side hash — and raw IP addresses are never stored, only salted SHA-256 hashes. Consent rules vary by jurisdiction, so confirm with whoever advises you on compliance, but there is no tracking cookie to disclose.

Will it slow my site down?

The tracker is about 2 KB, loads asynchronously and reports with sendBeacon, so it never blocks rendering. The dashboard is server-rendered; only charts and live polling use JS.

How much traffic can it handle on shared hosting?

Daily rollup tables back the date-range charts, so dashboards stay fast as the hits table grows. Run cron/rollup.php daily once you are past a few hundred thousand pageviews.

Can I track several sites, and subdomains?

Yes. Add as many sites as you like, each with its own tracking ID and timezone. If one snippet is installed across a main domain and its subdomains, every report can be filtered to a single subdomain.

How do I upgrade?

Upload the new files over the old ones and reload the dashboard. Schema changes apply themselves — there is no migration command to run. Leave config/config.php alone.

Getting the files

JS Stats is also available as a hosted service at stats.jidanshoppu.com — no install at all. For the self-hosted package, get in touch at stats@jidanshoppu.com.

Home · Changelog