Metrics
Aggregated metrics, breakdowns and timeseries across any dimension, with the attribution model you choose.
| Endpoint | Method | Path | Permission |
|---|---|---|---|
| Get metrics Aggregate metrics, breakdowns and timeseries | GET | /v1/metrics | metrics:read |
Base URL https://app.sourceloop.ai/api/v1
Get metrics
Aggregate metrics, breakdowns and timeseries
GET /v1/metrics
Requires metrics:read
Omit `group_by` for a single total. Add it for one row per dimension value, which also returns the window totals so the share each row represents is visible. Add `granularity` for a timeseries.
Note that a total and a timeseries are different queries: unique visitors cannot be summed across days without counting returning people twice, so the aggregate is computed once across the whole window.
curl -s -X GET "https://app.sourceloop.ai/api/v1/metrics?website=acme.com&period=last%2030%20days" \
-H "Authorization: Bearer $SOURCELOOP_API_KEY" const res = await fetch(
"https://app.sourceloop.ai/api/v1/metrics?website=acme.com&period=last%2030%20days",
{
method: "GET",
headers: {
Authorization: `Bearer ${process.env.SOURCELOOP_API_KEY}`,
},
},
);
const data = await res.json(); import os, requests
res = requests.get(
"https://app.sourceloop.ai/api/v1/metrics?website=acme.com&period=last%2030%20days",
headers={"Authorization": f"Bearer {os.environ['SOURCELOOP_API_KEY']}"},
)
data = res.json() Query parameters
websitestringWebsite domain, e.g. acme.com. Required only when the key covers more than one.
periodstringPlain-language period: "last 30 days", "yesterday", "July 2026", or "2026-07-01..2026-07-31". Ignored when from/to are given.
Example
last 30 daysfromstring (date-time)tostring (date-time)metricsstringrequiredComma-separated.
Allowed values25
visitorssessionspageviewseventsconversionsinfluenced_conversionsunique_convertersrevenuelifetime_valuecustomersavg_ltvrepeat_rateavg_orderscohort_mrrrevenue_per_customermilestonesconversion_ratepageviews_per_sessionrevenue_per_visitorspendimpressionsclicksroascacltv_cac
Example
visitors,conversions,conversion_rategroup_bystringSplit by one dimension, or up to four comma-separated for a nested breakdown such as channel,source. Omit for a single total.
Allowed values23
channelsourcemediumcampaignutm_termutm_contentreferrer_domainpagelanding_pagehostnamepage_titlecountryregioncitydevice_typebrowseroperating_systemresolutionplatformad_campaignad_setadcohort
Three of those are answered by a different store and behave differently:
- platform and ad_campaign join ad SPEND to the campaign that acquired each customer, which is what makes cac and ltv_cac available. They take one dimension at a time and cannot be crossed with traffic dimensions.
- resolution splits outcomes by WHY they had no journey (unmatched, predates tracking, imported contact) and is only available alongside credited metrics.
- cohort returns a retention curve instead of a ranking: rows are (cohort, period_index) and the window chooses which cohorts appear, never which payments count.
filterstring[]Repeatable, ANDed. Form: dimension:operator:value.
Operators6
eqneinnincontainsnot_contains
Filterable dimensions30
channelsourcemediumcampaignutm_termutm_contentreferrer_domainpagelanding_pagehostnamepage_titlecountryregioncitydevice_typebrowseroperating_systemresolutionevent_nameevent_typeidentifiedplatformad_campaignad_setadcampaign_typematch_typecompany_domaincrm_stagecrm_account_stage
Example
channel:in:paid_search,paid_socialgranularitystringReturn a daily time series instead of a single total. Only day is supported: the underlying store buckets by calendar day in the website timezone, so hour, week and month are rejected rather than silently returning days under another label.
Allowed values 1
day
attributionstringCredit conversions to a touchpoint using an attribution model instead of counting the event where the conversion fired. One of first_touch, last_touch, linear, u_shaped, time_decay, or up to five comma-separated to compare them in one response, which guarantees every model saw the same window and filters. Requires group_by, and only conversions and revenue can be attributed: a visitor has one channel at a time. When several models are given, each row nests one object per model; a null metric means that model truncated before reaching this value (see meta.truncated_models), which is not the same as zero.
Example
first_touch,last_touchstagesstringCount CRM and lifecycle milestones instead of tracked conversions: deal_created, deal_won, mql, trial_started, trial_converted, subscription_started, subscription_churned and the rest of the workspace stage vocabulary. A milestone is a different KIND of outcome from a conversion rather than a category of one, so the two are never blended. A milestone has no channel of its own, so this implies an attribution model and defaults to last_touch; the model used is echoed in meta.definitions. Deals are credited across the whole buying committee.
Example
deal_wonconjunctionstringHow repeated filters combine. Default and.
Allowed values 2
andor
only_paidbooleanRestrict to paid traffic: a paid medium, or the presence of an ad click id.
limitintegerDefault
50
Responses
-
200Rows plus meta -
400Something was wrong with the request or the credential. -
429Too many requests for this workspace in the current minute. Wait Retry-After seconds and repeat the request unchanged.