GraphQL Page Metrics

The metrics mutation combines page analytics, PageSpeed data and Google Search performance for one URL. Results are cached for one hour and may contain partial data when an analytics provider reports an error.

Start with PagibleAI GraphQL API for authentication and error handling. Use GraphQL Pages when you need to act on the results by updating or publishing content.

Request page metrics

mutation PageMetrics($url: String!, $days: Int, $lang: String) {
  metrics(url: $url, days: $days, lang: $lang) {
    errors
    views { key value rows { key value } }
    visits { key value rows { key value } }
    conversions { key value rows { key value } }
    durations { key value rows { key value } }
    countries { key value rows { key value } }
    referrers { key value rows { key value } }
    pagespeed { key value rows { key value } }
    impressions { key value rows { key value } }
    clicks { key value rows { key value } }
    ctrs { key value rows { key value } }
    queries { key impressions clicks ctr position }
  }
}
{
  "url": "https://www.example.com/guides/getting-started",
  "days": 30,
  "lang": "en"
}

metrics arguments

Argument
Type
Meaning
url
String!
Non-empty full page URL
days
Int
Lookback from 1 to 90 days; defaults to 30
lang
String
Optional language code; defaults to en

The caller needs page:metrics permission. The optional lang argument is accepted for API compatibility, but the current resolver does not vary provider requests or cache entries by language. Analytics, search and PageSpeed integrations must be configured for their corresponding fields to contain data.

Stats fields

Stats

Field
Type
Contents
errors
[String!]
Provider errors collected while other sources continue
views
[StatsNumber!]
Page views by day
visits
[StatsNumber!]
Visits by day
conversions
[StatsNumber!]
Conversions by day
durations
[StatsNumber!]
Average visit duration by day
countries
[StatsNumber!]
Visits by country
referrers
[StatsNumber!]
Visits by referring site
pagespeed
[StatsNumber!]
PageSpeed measurements
impressions
[StatsNumber!]
Google Search impressions
clicks
[StatsNumber!]
Google Search clicks
ctrs
[StatsNumber!]
Google Search click-through rates
queries
[StatsQuery!]
Search query performance

StatsNumber fields

StatsNumber

Field
Type
Meaning
key
String!
Date, country, referrer or metric name
value
Float
Numeric measurement
rows
[StatsNumber!]
Nested measurements when provided

StatsQuery fields

StatsQuery

Field
Type
Meaning
key
String!
Search query
impressions
Int
Search-result impressions
clicks
Int
Search-result clicks
ctr
Float
Click-through rate from 0 to 1
position
Float
Average search position

Example response

{
  "data": {
    "metrics": {
      "errors": [],
      "views": [
        {"key": "2026-07-01", "value": 150, "rows": []}
      ],
      "visits": [
        {"key": "2026-07-01", "value": 98, "rows": []}
      ],
      "countries": [
        {"key": "DE", "value": 54, "rows": []}
      ],
      "impressions": [
        {"key": "2026-07-01", "value": 1200, "rows": []}
      ],
      "clicks": [
        {"key": "2026-07-01", "value": 85, "rows": []}
      ],
      "ctrs": [
        {"key": "2026-07-01", "value": 0.071, "rows": []}
      ],
      "queries": [
        {
          "key": "laravel cms",
          "impressions": 1200,
          "clicks": 85,
          "ctr": 0.071,
          "position": 4.2
        }
      ]
    }
  }
}

Partial failure response

Each analytics source is collected independently. One failure can therefore produce an errors entry while other fields still contain useful data:

{
  "data": {
    "metrics": {
      "errors": [
        "Search provider credentials are missing"
      ],
      "views": [
        {"key": "2026-07-01", "value": 150, "rows": []}
      ],
      "impressions": null,
      "clicks": null,
      "ctrs": null,
      "queries": null,
      "pagespeed": [
        {"key": "performance", "value": 0.92, "rows": []}
      ]
    }
  }
}

Empty result response

{
  "data": {
    "metrics": {
      "errors": [],
      "views": [],
      "visits": [],
      "queries": []
    }
  }
}

An empty array means the configured provider returned no rows for that field. null usually means the resolver received no value for the field, often because its source failed or is unavailable. Handle those states separately.

Caching and partial failures

Analytics, search queries and PageSpeed results are cached for 3,600 seconds. If one source fails, the resolver adds its message to errors and still returns data collected from the other sources. Treat every stats field as nullable and show provider errors separately from an empty result.

Metrics cache keys

Data
Cache varies by
Lifetime
Analytics stats
Exact URL and days
3,600 seconds
Search performance
Exact URL and days
3,600 seconds
Search queries
Exact URL and days
3,600 seconds
PageSpeed
Exact URL
3,600 seconds

Normalize equivalent URLs before requesting metrics. Differences in scheme, host casing, trailing slashes or query strings create separate cache entries and may also refer to different records at the analytics provider.

Use metrics safely

Request only URLs the authenticated editor is allowed to analyze, and avoid exposing raw provider errors to public visitors. Metrics are an administrative GraphQL feature; use the read-only JSON:API or rendered pages for public content delivery.

Troubleshoot page metrics

Common metrics problems

Symptom
Likely cause
Resolution
URL must be non-empty
url was blank
Send the complete canonical page URL
Days validation error
days is outside 1 through 90
Use an integer in the supported range
Insufficient permissions
The user lacks page:metrics
Inspect me.permission and assigned roles
All fields are empty
Analytics integrations are not configured or have no rows
Check provider credentials, property IDs and date range
Only search fields are null
Search Console retrieval failed
Inspect errors and search-provider configuration
Only PageSpeed is null
PageSpeed retrieval failed
Check URL reachability and provider response
Numbers seem stale
The one-hour cache is still active
Wait for expiry before comparing a recent provider change
Duplicate-looking results
Different URL forms were requested
Normalize the URL before calling metrics
lang has no visible effect
The current resolver does not vary requests by language
Filter or label locales in the client until runtime support changes