Skip to main content

Pagination, Sorting & Advanced Filters

Complete reference for pagination, sorting, and advanced filtering across all API endpoints.


Pagination​

List endpoints return paginated results to handle large datasets efficiently.

Request Parameters​

ParameterTypeDefaultRangeDescription
pageinteger11+Page number (1-indexed)
page_sizeinteger501-1000Items per page (see per-endpoint maximum below)
note

The maximum page_size depends on the endpoint:

  • Up to 1000: /stats/pages, /stats/geo/countries, /stats/landing-pages, /stats/properties/values
  • Up to 100: /stats/sources, /stats/mediums, /stats/campaigns, /stats/terms, /stats/contents, /stats/referrers, /stats/channels, /stats/conversions, /stats/microconversions

Requesting a page_size above an endpoint's maximum returns a 422 validation error.

Response Format​

All paginated endpoints return a consistent response structure:

{
"data": [...],
"total": 250,
"page": 1,
"page_size": 50,
"has_next": true,
"has_prev": false
}
FieldTypeDescription
dataarrayArray of result items
totalintegerTotal count of items matching the query
pageintegerCurrent page number
page_sizeintegerItems per page
has_nextbooleantrue if more pages exist after this one
has_prevbooleantrue if pages exist before this one

Pagination Examples​

First page (default):

GET /stats/pages?site_id=my-site&period=30d

Second page with 100 items:

GET /stats/pages?site_id=my-site&period=30d&page=2&page_size=100

Calculate total pages:

const totalPages = Math.ceil(response.total / response.page_size);

Sorting​

Control the order of results with sort_by and sort_order parameters.

Request Parameters​

ParameterTypeDefaultDescription
sort_bystringvariesField to sort by
sort_orderstringdescSort direction: asc or desc

Available Sort Fields​

Traffic Endpoints​

For /stats/sources, /stats/campaigns, /stats/mediums, /stats/terms, /stats/contents, /stats/referrers, /stats/geo/countries:

FieldDescription
entrancesSession starts (default)
engaged_entrancesEngaged sessions (2+ pageviews)
page_viewsTotal page views
conversionsTotal conversions
revenueTotal revenue

Page Endpoints​

For /stats/pages, only two sort fields are accepted:

FieldDescription
page_viewsPage views (default)
entrancesEntry points to this page

Other values (such as conversions, revenue, or engaged_entrances) return a 422 validation error on this endpoint.

Conversion Endpoints​

For /stats/conversions:

FieldDescription
countNumber of conversions (default)
revenueTotal revenue
avg_valueAverage conversion value

Microconversion Endpoints​

For /stats/microconversions:

FieldDescription
countNumber of microconversions (default)

Sorting Examples​

Top sources by revenue:

GET /stats/sources?site_id=my-site&sort_by=revenue&sort_order=desc

Most-visited pages first:

GET /stats/pages?site_id=my-site&sort_by=page_views&sort_order=desc

Newest conversions first:

GET /stats/conversions?site_id=my-site&sort_by=count&sort_order=asc

Standard Filters​

Most endpoints support these common filter parameters:

UTM Filters​

ParameterDescriptionExample
utm_sourceTraffic sourcegoogle, facebook
utm_mediumTraffic mediumcpc, organic, email
utm_campaignCampaign namespring_sale
utm_termSearch term/keywordrunning shoes

Geographic Filters​

ParameterDescriptionExample
countryISO 3166-1 alpha-2 codeES, US, FR

Content Filters​

ParameterDescriptionExample
content_groupingContent group nameblog, products
path_filterURL path pattern/products/

Device Filters​

ParameterDescriptionExample
device_typeDevice categorydesktop, mobile, tablet
browserBrowser nameChrome, Safari
osOperating systemWindows, iOS

Segment Filter​

ParameterDescriptionExample
segmentSaved segment ID or namepaid-spain, mobile-users

Advanced Filters​

The filters parameter enables complex filtering with operators.

Syntax​

filters=field:operator:value,field2:operator:value2

Multiple filters are combined with AND logic.

Operators​

OperatorDescriptionExample
eqEqualscountry:eq:ES
neNot equalscountry:ne:US
containsContains substringutm_source:contains:google
not_containsDoes not containpath:not_contains:admin
regexRegex matchpath:regex:^/products/
not_regexRegex not matchpath:not_regex:^/api/
inIn list (values separated by |)country:in:ES|FR|DE
not_inNot in listutm_medium:not_in:cpc|ppc

Field Reference​

Available fields for advanced filtering:

FieldDescription
utm_sourceTraffic source
utm_mediumTraffic medium
utm_campaignCampaign name
utm_termSearch term
utm_contentAd content
countryCountry code
device_typeDevice type
browserBrowser name
osOperating system
pathPage URL path
referrerReferrer domain

Examples​

Spanish traffic only:

GET /stats/pages?site_id=my-site&filters=country:eq:ES

EU countries excluding UK:

GET /stats/sources?site_id=my-site&filters=country:in:ES|FR|DE|IT|PT,country:ne:GB

Product pages from Google:

GET /stats/pages?site_id=my-site&filters=path:contains:/products/,utm_source:eq:google

Non-branded organic traffic:

GET /stats/campaigns?site_id=my-site&filters=utm_medium:eq:organic,utm_campaign:not_contains:brand

Mobile users from social:

GET /stats/pages?site_id=my-site&filters=device_type:eq:mobile,utm_medium:in:social|social-media

Blog pages with regex:

GET /stats/pages?site_id=my-site&filters=path:regex:^/blog/2025/

Saved Segments​

Segments are pre-saved filter combinations that can be reused.

Using Segments​

Apply a segment with the segment parameter:

GET /stats/pages?site_id=my-site&segment=paid-spain

Segments can be referenced by ID or name.

Segment + Explicit Filters​

When you combine a segment with explicit filter parameters:

  1. Segment filters are applied first
  2. Explicit parameters override segment values
  3. Additional filters are ANDed together

Example:

If segment paid-traffic has utm_medium=cpc, and you add country=ES:

GET /stats/pages?site_id=my-site&segment=paid-traffic&country=ES

This applies: utm_medium=cpc AND country=ES


Filter Combinations​

Standard + Advanced Filters​

You can combine standard parameters with advanced filters:

GET /stats/pages?site_id=my-site&utm_medium=cpc&country=ES&filters=path:contains:/products/

This applies:

  • utm_medium = cpc (standard)
  • country = ES (standard)
  • path LIKE '%/products/%' (advanced)

Priority​

  1. Saved segment filters (lowest priority)
  2. Standard filter parameters
  3. Advanced filters (highest priority)

If the same field appears in multiple places, the higher priority wins.


Response with Filters​

The response includes filter metadata when applicable:

{
"data": [...],
"total": 45,
"page": 1,
"page_size": 50,
"has_next": false,
"has_prev": false,
"comparison": {
"entrances": 420,
"engaged_entrances": 336,
"page_views": 1250,
"conversions": 15,
"revenue": 1200.00
}
}

The comparison object (when compare is used) contains totals for the comparison period using the same filters.


Best Practices​

Pagination​

  1. Use reasonable page sizes - 50-100 items is optimal for most cases
  2. Don't skip pages - Iterate sequentially for complete data
  3. Cache total count - The total rarely changes during pagination

Filtering​

  1. Start broad, then narrow - Add filters incrementally
  2. Use segments for reusable filters - Avoid repeating complex filter strings
  3. Use in for multiple values - More efficient than multiple requests

Sorting​

  1. Default sort is usually optimal - Most endpoints default to the most useful sort
  2. Secondary sorting not supported - Results with equal values have undefined order
  3. Ascending for "worst" analysis - Use asc to find lowest performers

Code Examples​

Python - Paginate All Results​

import requests

def get_all_pages(site_id, period="30d"):
"""Fetch all pages with pagination."""
all_data = []
page = 1

while True:
response = requests.get(
"https://my.sealmetrics.com/api/v1/stats/pages",
headers={"X-API-Key": API_KEY},
params={
"site_id": site_id,
"period": period,
"page": page,
"page_size": 100,
"sort_by": "entrances",
"sort_order": "desc"
}
)
data = response.json()
all_data.extend(data["data"])

if not data["has_next"]:
break
page += 1

return all_data

JavaScript - Advanced Filter Builder​

class FilterBuilder {
constructor() {
this.filters = [];
}

equals(field, value) {
this.filters.push(`${field}:eq:${value}`);
return this;
}

contains(field, value) {
this.filters.push(`${field}:contains:${value}`);
return this;
}

in(field, values) {
this.filters.push(`${field}:in:${values.join('|')}`);
return this;
}

notEquals(field, value) {
this.filters.push(`${field}:ne:${value}`);
return this;
}

build() {
return this.filters.join(',');
}
}

// Usage
const filters = new FilterBuilder()
.in('country', ['ES', 'FR', 'DE'])
.equals('utm_medium', 'cpc')
.contains('path', '/products/')
.build();

// Result: "country:in:ES|FR|DE,utm_medium:eq:cpc,path:contains:/products/"

PHP - Sorted and Filtered Request​

<?php
$params = http_build_query([
'site_id' => 'my-site',
'period' => '30d',
'filters' => 'country:in:ES|FR,utm_medium:eq:organic',
'sort_by' => 'revenue',
'sort_order' => 'desc',
'page' => 1,
'page_size' => 50
]);

$response = file_get_contents(
"https://my.sealmetrics.com/api/v1/stats/sources?{$params}",
false,
stream_context_create([
'http' => [
'header' => "X-API-Key: {$apiKey}"
]
])
);

$data = json_decode($response, true);
foreach ($data['data'] as $source) {
echo "{$source['utm_source']}: €{$source['revenue']}\n";
}
Written and maintained by the Sealmetrics Team