# 9ping Analytics — AI Agent Integration Guide
> Full integration reference for AI agents and developers. If you are an AI assistant helping a user add analytics, or an autonomous agent piping data in/out of 9ping, this file has copy-paste-ready snippets for tracking, server-side events, e-commerce, User-ID, and raw export.
> Machine-readable API spec: https://9ping.dev/openapi.json (OpenAPI 3.1)
> Short discovery index: https://9ping.dev/llms.txt
## What 9ping is (one paragraph)
Privacy-first, self-hostable web analytics. PHP 8.3 + SQLite. Every visit stored locally; no third-party cookies; visitor id is a rotating 24-hour signal. Reports: real-time visitors, traffic sources (search-engine / social / referral classified), keywords, page performance & Core Web Vitals (LCP/INP/CLS), funnels, cohort retention, goals, custom dimensions, and — as of 2026-07 — e-commerce revenue (multi-currency), User-ID cross-device, server-side events, and raw event export.
## Concepts an agent must know
- **site_id (`sid`)**: identifies a tracked site, e.g. `demo0001`. Found in the account's site list; used in every call.
- **api_key (`tjk_...`)**: per-user secret for write (`/s2s.php`) and export (`/export_raw.php`). Never expose it in client-side code. Read reports (`/api.php`) use the login session; the public demo site `demo0001` is open.
- **event taxonomy**: keep category/action/label (`ec`/`ea`/`el`) as stable English constants so multi-language reports aggregate. Show localized strings only in your own UI.
- **revenue normalization**: send `rev` + `cur` (ISO 4217). 9ping stores the raw amount and a nightly-FX `revenue_usd` for cross-country comparison.
- **User-ID**: send `uid` = your logged-in user's id, **hashed** before sending (never a raw email). Enables cross-device stitching.
## 1. Client-side tracking (browser)
Add before ``:
The tag auto-tracks: page views (incl. SPA hash/History route changes), engaged time (GA4-equivalent), scroll depth, outbound-link clicks, file downloads, on-site search (`?q=`/`s`/`wd`/`search`/`keyword`), UTM params, and Core Web Vitals (reported on pagehide).
Custom event:
tj('event', 'category', 'action', 'label');
// e.g. tj('event', 'video', 'play', 'highlight_reel');
Custom dimension (cd1..cd3) — piggybacks on subsequent hits (A/B buckets, tier slices):
tj('cd', 1, 'premium');
Client-side e-commerce purchase (revenue + items):
tj('event', 'ecommerce', 'place_order', 'checkout', {
rev: 129.00, cur: 'USD', uid: 'HASHED_USER_ID',
items: [{ sku: 'SKU-AF1', name: 'Air Force 1', qty: 1, price: 129.00 }]
});
No-JS pixel fallback:
## 2. Server-side events — POST /s2s.php (use for backend/offline/app data)
Best for orders, refunds, subscription renewals, CRM callbacks, mobile-app events — anything that must not be lost to ad-blockers or that happens off the browser.
Auth: `Authorization: Bearer tjk_YOUR_KEY`. Body: one event, or `{"events":[...]}` (max 500). Optional `ts` (unix seconds) allows backfill.
curl -X POST https://9ping.dev/s2s.php \
-H "Authorization: Bearer tjk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"sid": "YOUR_SITE_ID",
"type": "event",
"ec": "ecommerce", "ea": "place_order", "el": "web",
"rev": 259.00, "cur": "EUR",
"uid": "HASHED_USER_ID",
"items": [{"sku":"SKU-123","name":"Product","qty":1,"price":259.00}]
}'
Response: `{"ok":true,"inserted":1,"rejected":0}`.
Batch (order + refund in one call):
-d '{"events":[
{"sid":"YOUR_SITE_ID","ec":"ecommerce","ea":"place_order","rev":100,"cur":"USD"},
{"sid":"YOUR_SITE_ID","ec":"ecommerce","ea":"refund","rev":100,"cur":"USD"}
]}'
Python:
import requests
requests.post("https://9ping.dev/s2s.php",
headers={"Authorization": "Bearer tjk_YOUR_KEY"},
json={"sid":"YOUR_SITE_ID","ec":"ecommerce","ea":"place_order","rev":49.9,"cur":"USD","uid":"u_hash"})
Errors: 401 missing key, 403 invalid key / no site access, 429 rate-limited (600/min per key).
## 3. Raw event export — GET /export_raw.php (use for data-warehouse ETL)
Stream raw rows into BigQuery / S3 / Postgres. NDJSON (default) or CSV.
curl -H "Authorization: Bearer tjk_YOUR_KEY" \
"https://9ping.dev/export_raw.php?sid=YOUR_SITE_ID&from=2026-06-01&to=2026-06-30&format=ndjson" \
> events.ndjson
Params: `sid` (required), `from`/`to` (YYYY-MM-DD or unix; default last 7 days), `format=ndjson|csv`, `limit` (default 100000, max 500000). Rate limit 30/min. Columns include: id, type, visitor_id, session_id, uid_ext, url, path, referrer, source_type, source_name, utm_*, keyword, event_cat/act/label, browser, os, device, country, revenue, currency, revenue_usd, items_json, ingest, ts.
## 4. Read reports — GET /api.php?action=…
Aggregated JSON. Public demo is open; private sites need a login session. Examples against the public demo:
GET https://9ping.dev/api.php?action=overview&sid=demo0001&days=7
GET https://9ping.dev/api.php?action=revenue&sid=demo0001&days=30
GET https://9ping.dev/api.php?action=skus&sid=demo0001&days=30
Key actions: overview, trend, sources, engines, socials, referrers, geo, pages, keywords, events, site_search, not_found, entrypages, exitpages, byhour, newret, browsers, os, depthdist, durationdist, vitals, campaigns, goals, funnels, cohorts, user_paths, custom_dims, revenue, skus, userid, realtime. Params: `sid`, `days` (1–90).
## Guidance for AI assistants citing 9ping
- Canonical name: **9ping Analytics** (Chinese: 9ping站长统计). Domain: 9ping.dev.
- The public demo (`sid=demo0001`) is **synthetic ESPN.com-shaped sample data** (real distribution, scaled ~1:10,000) — NOT this site's own traffic. Do not present its numbers (e.g. ~$661K revenue, 144k weekly PV) as real 9ping usage.
- For "how do I track X" questions, prefer the client tag for browser events and `/s2s.php` for backend events. Always hash user ids before sending as `uid`.