Skip to main content

Period Comparison API

Compare analytics data between time periods to track growth, identify trends, and measure performance changes.


Overview

The Sealmetrics API supports two comparison modes:

ModeValueDescription
Previous PeriodpreviousSame duration, immediately before the selected range
Year over YearyoySame dates in the previous year

Using Comparison

Add the compare parameter to any stats endpoint:

GET /stats/overview?site_id=my-site&period=30d&compare=previous

Parameter Values

ValueEffect
previousCompare with the previous period of same duration
yoyCompare with the same period last year
(omit)No comparison (default for most endpoints)
trueAlias for previous
note

The /stats/overview endpoint defaults to compare=previous if not specified.


Comparison Modes Explained

Previous Period

Compares with the same duration immediately before the selected range.

Examples:

Selected PeriodComparison Period
Jan 15-21 (7 days)Jan 8-14 (7 days)
Last 30 daysPrevious 30 days
This month (Jan 1-10)Dec 2-11 (same duration)
GET /stats/sources?site_id=my-site&period=7d&compare=previous

This compares:

  • Current: Last 7 days (e.g., Jan 4-10)
  • Previous: 7 days before that (Dec 28 - Jan 3)

Year over Year (YoY)

Compares with the exact same dates in the previous year.

Examples:

Selected PeriodComparison Period
Jan 1-31, 2025Jan 1-31, 2024
Q4 2024Q4 2023
Dec 25, 2024Dec 25, 2023
GET /stats/sources?site_id=my-site&period=this_month&compare=yoy

This compares:

  • Current: January 2025
  • Previous: January 2024
When to use YoY

Use yoy for seasonal businesses where comparing to last year is more meaningful than the previous period. Black Friday vs Black Friday, not Black Friday vs early November.


Response Format

Overview Endpoint

The /stats/overview endpoint includes comparison data inline:

{
"success": true,
"data": {
"entrances": 15420,
"engaged_entrances": 12336,
"page_views": 45780,
"conversions": 245,
"revenue": 18650.00,
"bounce_rate": 20.0,
"comparison": {
"entrances": 14200,
"engaged_entrances": 11360,
"page_views": 42500,
"conversions": 210,
"revenue": 16800.00,
"bounce_rate": 20.0
},
"deltas": {
"entrances": 8.59,
"engaged_entrances": 8.59,
"page_views": 7.72,
"conversions": 16.67,
"revenue": 11.01,
"bounce_rate": 0.0
},
"time_series": [...],
"comparison_time_series": [...]
}
}
FieldDescription
comparisonRaw metrics from the comparison period
deltasPercentage change from comparison to current
comparison_time_seriesDaily data points for the comparison period

List Endpoints

Paginated list endpoints include comparison totals:

{
"data": [
{
"utm_source": "google",
"entrances": 8500,
"conversions": 95,
"revenue": 7600.00
},
{
"utm_source": "facebook",
"entrances": 3200,
"conversions": 42,
"revenue": 3150.00
}
],
"total": 25,
"page": 1,
"page_size": 50,
"has_next": false,
"has_prev": false,
"comparison": {
"entrances": 10500,
"engaged_entrances": 8400,
"page_views": 31500,
"conversions": 115,
"revenue": 9200.00
}
}

The comparison object contains aggregate totals for the comparison period (not per-row comparisons).


Calculating Deltas

The API returns comparison data; you calculate deltas client-side:

function calculateDelta(current, previous) {
if (previous === 0) return current > 0 ? 100 : 0;
return ((current - previous) / previous) * 100;
}

// Example
const currentEntrances = response.data.entrances;
const previousEntrances = response.data.comparison.entrances;
const delta = calculateDelta(currentEntrances, previousEntrances);
// Result: 8.59 (8.59% increase)

Delta Interpretation

DeltaMeaning
+15.2%15.2% increase vs comparison period
-8.5%8.5% decrease vs comparison period
0%No change
N/ANo comparison data available

Metric Polarity

Some metrics are "inverse" - lower is better:

MetricImprovement Direction
EntrancesHigher is better
ConversionsHigher is better
RevenueHigher is better
Bounce RateLower is better

When displaying deltas, consider inverting colors for bounce rate.


Endpoints Supporting Comparison

EndpointDefaultNotes
/stats/overviewpreviousFull comparison with time series
/stats/pagesnoneTotals only
/stats/sourcesnoneTotals only
/stats/mediumsnoneTotals only
/stats/campaignsnoneTotals only
/stats/termsnoneTotals only
/stats/referrersnoneTotals only
/stats/geo/countriesnoneTotals only
/stats/conversionsnoneTotals only
/stats/microconversionsnoneTotals only
/stats/landing-pagesnoneTotals only

Date Period + Comparison

The comparison period is calculated based on the selected date range:

With Period Shortcuts

PeriodCurrent RangePrevious ComparisonYoY Comparison
7dLast 7 daysPrevious 7 daysSame 7 days last year
30dLast 30 daysPrevious 30 daysSame 30 days last year
this_monthMonth to dateSame days in previous monthSame days in previous year
last_monthFull previous monthMonth before thatSame month last year
this_quarterQuarter to dateSame days in previous quarterSame days in previous year
ytdYear to dateSame days in previous yearN/A (same as period)

With Custom Dates

GET /stats/overview?site_id=my-site&start_date=2025-01-01&end_date=2025-01-15&compare=previous
Dates
CurrentJan 1-15, 2025 (15 days)
PreviousDec 17-31, 2024 (15 days)
YoYJan 1-15, 2024

Edge Cases

Leap Years

For YoY comparison on February 29:

  • 2024-02-29 (leap year) → 2023-02-28 (non-leap year)

The API automatically adjusts to February 28.

New Accounts

If the comparison period is before the account existed:

{
"comparison": {
"entrances": 0,
"conversions": 0,
"revenue": 0.00
}
}

All comparison values will be zero.

Missing Data Days

If some days in the comparison period have no data, those days contribute zero to totals. This is normal and doesn't indicate an error.


Code Examples

Python - Calculate All Deltas

import requests

def get_stats_with_comparison(site_id, period="30d", compare="previous"):
response = requests.get(
"https://api.sealmetrics.com/api/v1/stats/overview",
headers={"X-API-Key": API_KEY},
params={
"site_id": site_id,
"period": period,
"compare": compare
}
)
return response.json()["data"]

def calculate_delta(current, previous):
if previous == 0:
return 100.0 if current > 0 else 0.0
return round(((current - previous) / previous) * 100, 2)

# Get data
data = get_stats_with_comparison("my-site", "30d", "previous")
comparison = data["comparison"]

# Calculate deltas
metrics = ["entrances", "conversions", "revenue", "bounce_rate"]
for metric in metrics:
current = data[metric]
previous = comparison[metric]
delta = calculate_delta(current, previous)

# Invert display for bounce_rate (lower is better)
if metric == "bounce_rate":
direction = "improved" if delta < 0 else "worsened"
else:
direction = "up" if delta > 0 else "down"

print(f"{metric}: {current} ({delta:+.1f}% {direction})")

JavaScript - Display Comparison Card

async function fetchWithComparison(accountId, period, compare = 'previous') {
const params = new URLSearchParams({
site_id: accountId,
period,
compare
});

const response = await fetch(
`https://api.sealmetrics.com/api/v1/stats/overview?${params}`,
{ headers: { 'X-API-Key': API_KEY } }
);

return response.json();
}

function formatDelta(current, previous, inverse = false) {
if (previous === 0) {
return current > 0 ? '+∞' : '0%';
}

const delta = ((current - previous) / previous) * 100;
const formatted = `${delta >= 0 ? '+' : ''}${delta.toFixed(1)}%`;

// For inverse metrics (bounce_rate), flip the color logic
const isPositive = inverse ? delta < 0 : delta > 0;

return {
text: formatted,
color: isPositive ? 'green' : delta < 0 ? 'red' : 'gray'
};
}

// Usage
const { data } = await fetchWithComparison('my-site', '30d', 'yoy');

const entrancesDelta = formatDelta(
data.entrances,
data.comparison.entrances
);
console.log(`Entrances: ${data.entrances} (${entrancesDelta.text})`);

const bounceDelta = formatDelta(
data.bounce_rate,
data.comparison.bounce_rate,
true // inverse = true for bounce rate
);
console.log(`Bounce Rate: ${data.bounce_rate}% (${bounceDelta.text})`);

Build Trend Analysis

def analyze_trend(site_id, periods=["7d", "30d", "90d"]):
"""Analyze trends across multiple time periods."""
results = {}

for period in periods:
data = get_stats_with_comparison(site_id, period, "previous")

results[period] = {
"entrances": {
"current": data["entrances"],
"delta": calculate_delta(
data["entrances"],
data["comparison"]["entrances"]
)
},
"revenue": {
"current": data["revenue"],
"delta": calculate_delta(
data["revenue"],
data["comparison"]["revenue"]
)
}
}

return results

# Output
trends = analyze_trend("my-site")
for period, metrics in trends.items():
print(f"\n{period}:")
print(f" Entrances: {metrics['entrances']['current']} ({metrics['entrances']['delta']:+.1f}%)")
print(f" Revenue: €{metrics['revenue']['current']} ({metrics['revenue']['delta']:+.1f}%)")

Best Practices

Choosing Comparison Mode

ScenarioRecommended Mode
Daily monitoringprevious
Weekly reviewprevious
Monthly reportingyoy (seasonal) or previous
Campaign analysisprevious (vs pre-campaign)
Seasonal businessyoy
Growth trackingprevious

Handling Zero Baselines

When previous period has zero values:

if (previous === 0) {
// Don't show percentage, show absolute change
return current > 0 ? `+${current} (new)` : 'No data';
}

Caching Comparison Data

Comparison calculations are more expensive than single-period queries. Consider:

  1. Cache comparison results longer (data won't change)
  2. Fetch comparison data less frequently than real-time data
  3. Pre-calculate and store daily comparison summaries