Quickstart

From a script tag to a classified session. Around fifteen minutes, most of it waiting for real traffic.

Before you start

You need an account and a registered project. Registration creates the account, origin and project records that enable scheduled aggregation and digests. Contact ed@bayis.co.uk with the domain you want to measure.

You will receive:

  • an origin, the site URL, for example https://example.com
  • a project identifier, for example myapp/home
  • credentials for the dashboard and CLI

The project identifier is a namespace. One origin can carry several projects if you want the marketing site and the application measured separately.

1. Add the client

Place this before the closing </body> tag on every page you want measured.

<script src="https://www.clientlog.bayis.co.uk/clientlog.js"></script>
<script>
  const logger = clientlog.createLogger({
    endpoint: "https://api.dev.clientlog.bayis.co.uk/v1/event",
    project: "myapp/home"
  });
</script>

That is the whole installation. Page views, exits with dwell time, scroll depth and clicks are captured with no further configuration. Every default is adjustable; see the client reference.

The project value must match the identifier you were given exactly. A mismatch means events are accepted and never aggregated, because the scheduler looks for a project that does not exist.

2. Confirm events are arriving

Load a page, scroll down it, click a link. Then ask the pipeline what it received:

pip install clientlog-cli
clientlog login you@example.com

clientlog --origin https://example.com --project myapp/home events names
ACTION                          LAST SEEN
page_view.home                  2026-08-31 14:02:11
page_view.pricing               2026-08-31 14:02:19
page_exit.home                  2026-08-31 14:02:19
scroll                          2026-08-31 14:02:14
click                           2026-08-31 14:02:18

Page identity is in the action name, so page_view.pricing is a distinct action from page_view.home. This is what makes journeys and landing pages readable without custom instrumentation.

An empty result means nothing is reaching the pipeline. Set debug: true in the options and check the browser console for the outgoing requests, then confirm the endpoint and project values.

3. Send a custom event

Automatic events describe browsing. Custom events describe your product. Call log at the moment something meaningful happens.

logger.log("user.signup.success", { plan: "standard" });

Name events as a dotted hierarchy, most general segment first, so prefixes stay searchable:

user.signup.success
user.signup.failure
user.payment.request
user.payment.success

Payloads are capped at 512 characters server-side. Send short values and identifiers. Do not send email addresses, names, or anything a user typed.

More in events.

4. Wait for aggregation

Events are enriched within seconds. Sessions are built on a schedule, so a session appears once its window has been aggregated. To see one immediately:

clientlog --origin https://example.com --project myapp/home \
  trigger aggregation --hours 1

Then list what was produced:

clientlog --origin https://example.com --project myapp/home \
  sessions list --limit 10
Session ID                   Start Time           Events   Duration   Tags
------------------------------------------------------------------------------
1782693098872-7xzwuxbzd      2026-08-31 14:02     8        142.4      visited

5. Write a rule

A rule is a JSONLogic expression evaluated against a session. When it matches, it writes a tag.

Create rules.yaml:

origin: https://example.com
project: myapp/home

rules:
  - rule_id: any_session
    tag: visited
    logic: {">=": [{"var": "session.num_events"}, 1]}

  - rule_id: bounce
    tag: bounce
    description: One page and nothing further
    logic: {"==": [{"var": "session.unique_actions"}, 1]}

  - rule_id: pricing_visitor
    tag: pricing
    description: Reached the pricing page
    logic: {"in": ["page_view.pricing", {"var": "session.actions"}]}

  - rule_id: signup
    tag: converted
    notification_target: email
    description: Completed a signup
    logic: {"in": ["user.signup.success", {"var": "session.actions"}]}

Check it against deployed state, then apply it:

clog plan  --file rules.yaml --origin https://example.com --project myapp/home
clog apply --file rules.yaml --origin https://example.com --project myapp/home

notification_target: email sends a message the moment that rule matches. Use it for signals worth interrupting yourself for. Everything else belongs in the weekly digest.

Full reference in rules.

6. Read the digest

The digest arrives at the address registered with your project, carrying session counts, bot ratio, referrers, landing pages, tag distribution, device and region splits, and journey structure, each compared against the previous window.

See reading the digest for what each block means.

Where to go next

  • Client reference: every option, custom events, single-page applications, session identity.
  • Events: the event shape, naming, what enrichment adds.
  • Rules: the session context and JSONLogic patterns.
  • CLI: command reference.