Skip to main content

What is QAL?

QAL (Query Analytics Language) is the query language spoken by the QA ZERO API. It is a declarative JSON format — not SQL, not a DSL with parentheses and operators. You construct a query by building a JSON object and sending it to /query.

The shape, in one object

Every valid QAL query has exactly these top-level keys:

{
"tracking_id": "...", // which site to query
"materials": [...], // data surfaces this query touches
"time": {...}, // start / end / timezone
"make": {...}, // named views (the actual work)
"result": {...} // which view to return, and how
}

Any other top-level key is rejected. This is intentional: the shape is small enough to fit in a single mental model, and the validator can reject structural mistakes before they reach the executor.

The five pieces, explained

tracking_id

A string that identifies which site on this install to query. The list of tracking_ids you can use is returned by /guide. Do not hardcode these across servers.

materials

An array of objects naming the data surfaces this query reads from. Material names come from materials.yaml (e.g. allpv, gsc, click_event). If a material name is not in the spec, the query is rejected.

time

The time window, as { start, end, tz }. start and end are ISO-8601 timestamps. tz is an IANA timezone such as Asia/Tokyo or UTC. There is no default time range — "all time" queries are intentionally unavailable.

make

A map of named views. Each view has:

  • from — the source material.
  • keep — columns to carry forward.
  • Optionally: filter, join, add/calc, sort.

Views are the actual working units of QAL. You can define multiple views in one make block and chain them (one view can use another as its from).

result

Tells the executor which view to return:

  • use — the name of the view in make to return.
  • limit — maximum row count.
  • count_only — if true, return only a row count and ignore limit.

Worked example

A minimal query that returns the 10 most-viewed pages over the last seven days:

{
"tracking_id": "abc123",
"materials": [{ "name": "allpv" }],
"time": {
"start": "2026-04-07T00:00:00",
"end": "2026-04-14T00:00:00",
"tz": "Asia/Tokyo"
},
"make": {
"top_pages": {
"from": "allpv",
"keep": ["url"],
"calc": { "views": { "count": "*" } },
"sort": [{ "column": "views", "direction": "desc" }]
}
},
"result": { "use": "top_pages", "limit": 10 }
}

That is the whole shape. Once you have internalized this, the rest of the documentation is just details on what each piece accepts.

Where to go next