Analytics & Access Log
Every Cell records its own traffic — no script tag, no code change, nothing to configure. The dashboard's Overview tab shows who is visiting (humans and bots, countries, browsers, top paths) and how the Cell is behaving (error rate, response time, scheduled and sensor activity). The Access log tab lists individual requests.
Analytics describe traffic; they are not billing. Tissue bills CPU time and stored bytes only — requests are free and unmetered.
What is measured
For each request the platform records the UTC hour, whether the caller looked like a human browser or a bot, the response status, and the response time. Human traffic is additionally broken down by country, browser family, request path, and referrer site; bot traffic is broken down by crawler name.
Platform-originated invocations — Pulse fires and Synapse sensor dispatches — are counted as events, separately from visitor traffic. A Cell on a * * * * * schedule shows 1,440 pulse events a day, not 1,440 visitors.
All aggregation happens on Tissue's own infrastructure. There is no third-party analytics service, no tracking pixel, and nothing is loaded into your visitors' browsers.
Visitors, without cookies
Unique-visitor counts use no cookie and no stored identifier. Each request is keyed by a hash of the visitor's IP address, user agent, the Cell's address, and a salt that rotates at UTC midnight:
visitor = sha256(daily_salt ‖ ip ‖ user_agent ‖ cell_address)
The raw IP and user agent never enter the analytics store — only the hash does, and once the salt rotates, yesterday's hashes cannot be linked to today's. The same person is a "new visitor" every day, so visitor counts are approximate by design; the dashboard marks them as such.
Bot classification
Classification is user-agent based. Well-known crawlers (search engines, AI crawlers, uptime monitors, link-preview fetchers) are matched by name; anything else that self-identifies as automated is grouped under Unknown agents. The dashboard tags named crawlers as Search, AI crawler, or Monitor — useful when deciding what your robots.txt should say, because you can see how much of your traffic is AI crawlers and which ones.
Two honest caveats: a bot that fakes a normal browser user agent is counted as a browser, and a privacy proxy can shift a visitor's country. Treat the split as a good estimate, not an audit.
Countries
The visitor's IP is resolved to a two-letter country code at ingest, and only the code is stored in analytics. Geolocation runs locally against the DB-IP Lite database — IP geolocation by DB-IP — with no lookup ever leaving the platform.
Retention
| Data | Kept for |
|---|---|
| Access log (individual requests, incl. IP) | 30 days |
| Hourly analytics (traffic, countries, browsers, paths, bots) | 90 days |
| Daily visitor counts | 400 days |
Deleting a Cell deletes its analytics.
Analytics API
Base URL: https://api.tissue.systems · Auth: Authorization: Bearer <token> (CLI JWT or tok_ API token) · Scope: cells:read
GET /v1/cells/{address}/analytics
Returns the rollups behind the Overview tab. hours may be 24, 168 (7 days), or 720 (30 days); other values snap to the nearest window. Default is 168.
curl "https://api.tissue.systems/v1/cells/dd0d1cd5x7k2q/analytics?hours=24" \
-H "Authorization: Bearer $TISSUE_TOKEN"
{
"series": [{ "t": "2026-08-09T14", "requests": 412, "human": 371,
"bots": 41, "s4xx": 3, "s5xx": 0, "avgMs": 12 }],
"totals": { "requests": 5210, "human": 4903, "bots": 307,
"s2xx": 5100, "s3xx": 80, "s4xx": 27, "s5xx": 3, "avgMs": 14 },
"visitors": { "human": 892, "bots": 55, "approx": true },
"countries": [["US", 2101], ["DE", 512]],
"browsers": [["Chrome", 2900], ["Safari", 1203]],
"botAgents": [["Googlebot", 120], ["~unknown", 88]],
"paths": [["/", 3100], ["/api/notes", 900]],
"referrers": [["news.ycombinator.com", 340]],
"events": { "http": 5210, "pulse": 288, "sensor": 0 }
}
series is gap-filled (quiet hours appear as zeros). Breakdown lists are [name, count] pairs for human traffic only; bots are broken down in botAgents, where ~unknown collects unnamed agents and ~other folds the tail past the top entries.
GET /v1/cells/{address}/access-log
Returns individual requests, newest first: { "entries": [...], "total": n }.
| Parameter | Meaning |
|---|---|
limit, offset |
Paging (default limit=25) |
status |
Exact code (404) or class (4xx) |
method |
HTTP method |
event |
http, pulse, or sensor |
bot |
true (bots only) or false (humans only) |
path |
Substring match on the URL path |
curl "https://api.tissue.systems/v1/cells/dd0d1cd5x7k2q/access-log?status=5xx&bot=false" \
-H "Authorization: Bearer $TISSUE_TOKEN"
Entries carry the request line, status, duration, IP, referrer, and — when resolved — country, browser, bot, event, and the daily visitor hash.