Kanorio

API 參考

Analytics

Management API: GET /sites/{id}/analytics/overview, GET /sites/{id}/analytics/pages, GET /sites/{id}/analytics/bots, …

這頁只有英文版。API 參考、Webhook 事件與變更紀錄維持英文,和程式碼裡的欄位名稱、錯誤碼一致。
Base URL https://app.kanorio.com/api/v1ErrorsPagination

Analytics overview

GET/sites/{id}/analytics/overview
betaanalytics:viewheavy (20/minute per token, plus 20/minute per site)

Get website traffic overview for the selected period (default 30 days, or a custom from/to date range in the website's timezone): totals, previous-period comparison, daily series, devices, top traffic sources, UTM campaigns, buttons, and countries. When the range starts before traffic source data became complete, dataCoverage explains how topSources and topUtm are affected. Errors: FORBIDDEN, VALIDATION, RATE_LIMITED (per-site analytics limit), ANALYTICS_BUSY.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • daysinteger · query

    Number of completed calendar days ending yesterday in the website's timezone (1 to 3650, defaults to 30; days=1 means yesterday; ignored when from and to are provided).

  • fromstring · query

    Start calendar date (YYYY-MM-DD) in the website's timezone, inclusive. Must be paired with to.

  • tostring · query

    End calendar date (YYYY-MM-DD) in the website's timezone, inclusive (up to yesterday in site timezone). Must be paired with from.

Response 200

  • daysintegerrequired

    Number of days in the selected range.

  • fromstringrequired

    Start date (YYYY-MM-DD) in the website's timezone.

  • tostringrequired

    End date (YYYY-MM-DD) in the website's timezone.

  • timezonestringrequired

    IANA timezone used for day boundaries.

  • dataStatus"ok" | "no_traffic" | "pending_aggregation"required

    ok when traffic data exists; no_traffic when the site had 0 visits in this range; pending_aggregation when filled from raw events before the nightly rollup.

  • totalsobjectrequired
  • totals.pageviewsintegerrequired

    Total pageviews in the period.

  • totals.uniqueVisitorsintegerrequired

    Sum of daily unique visitors in the period.

  • totals.sessionsintegerrequired

    Total visitor sessions (30-minute idle boundary).

  • totals.clicksintegerrequired

    Total custom button clicks.

  • totals.formSubmitsintegerrequired

    Total non-spam form submissions.

  • totals.socialClicksintegerrequired

    Total external brand/social link clicks.

  • previousPeriodobjectrequired

    Totals from the immediately preceding period of equal length.

  • previousPeriod.fromstringrequired

    Previous period start date (YYYY-MM-DD).

  • previousPeriod.tostringrequired

    Previous period end date (YYYY-MM-DD).

  • previousPeriod.totalsobjectrequired
  • previousPeriod.totals.pageviewsintegerrequired

    Total pageviews in the period.

  • previousPeriod.totals.uniqueVisitorsintegerrequired

    Sum of daily unique visitors in the period.

  • previousPeriod.totals.sessionsintegerrequired

    Total visitor sessions (30-minute idle boundary).

  • previousPeriod.totals.clicksintegerrequired

    Total custom button clicks.

  • previousPeriod.totals.formSubmitsintegerrequired

    Total non-spam form submissions.

  • previousPeriod.totals.socialClicksintegerrequired

    Total external brand/social link clicks.

  • trendsobjectrequired
  • trends.pageviewsinteger | nullrequired

    Percentage change vs. the previous period of equal length (null when previous period was 0).

  • trends.uniqueVisitorsinteger | nullrequired

    Percentage change vs. the previous period of equal length.

  • trends.sessionsinteger | nullrequired

    Percentage change vs. the previous period of equal length.

  • trends.clicksinteger | nullrequired

    Percentage change vs. the previous period of equal length.

  • trends.formSubmitsinteger | nullrequired

    Percentage change vs. the previous period of equal length.

  • trends.socialClicksinteger | nullrequired

    Percentage change vs. the previous period of equal length.

  • dailyobject[]required

    Day-by-day series covering every day in [from, to].

  • daily[].datestringrequired

    Calendar date (YYYY-MM-DD) in the website's timezone.

  • daily[].pageviewsintegerrequired

    Pageviews on this date.

  • daily[].uniqueVisitorsintegerrequired

    Unique visitors on this date.

  • daily[].sessionsintegerrequired

    Visitor sessions on this date.

  • daily[].clicksintegerrequired

    Button clicks on this date.

  • daily[].formSubmitsintegerrequired

    Form submissions on this date.

  • daily[].socialClicksintegerrequired

    External link clicks on this date.

  • devicesobjectrequired
  • devices.mobileintegerrequired

    Unique visitors on mobile devices.

  • devices.desktopintegerrequired

    Unique visitors on desktop devices.

  • devices.tabletintegerrequired

    Unique visitors on tablet devices.

  • topSourcesobject[]required

    Top entry traffic sources (google, direct, chatgpt, etc.).

  • topSources[].namestringrequired

    Channel, button, link, or country identifier.

  • topSources[].valueintegerrequired

    Count in the selected period.

  • topUtmobject[]required

    Top UTM campaigns or source/medium pairs.

  • topUtm[].namestringrequired

    Channel, button, link, or country identifier.

  • topUtm[].valueintegerrequired

    Count in the selected period.

  • topButtonsobject[]required

    Top clicked custom CTA buttons.

  • topButtons[].namestringrequired

    Channel, button, link, or country identifier.

  • topButtons[].valueintegerrequired

    Count in the selected period.

  • topCountriesobject[]required

    Top visitor countries (ISO 3166-1 alpha-2).

  • topCountries[].namestringrequired

    Channel, button, link, or country identifier.

  • topCountries[].valueintegerrequired

    Count in the selected period.

  • dataCoverageobject

    Present only when the selected range starts before trafficSourcesCompleteFrom; do not read the direct share of that earlier part as real traffic distribution.

  • dataCoverage.trafficSourcesCompleteFromstringrequired

    Local date (YYYY-MM-DD, website timezone) from which topSources and topUtm are fully recorded.

  • dataCoverage.notestringrequired

    How data before trafficSourcesCompleteFrom affects topSources and topUtm.

Errors

  • FORBIDDEN 403
  • VALIDATION 400
  • RATE_LIMITED 429 · per-site analytics limit
  • ANALYTICS_BUSY 429

MCP tool analytics_overview

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/analytics/overview?days=30" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "days": 30,
  "from": "2026-09-23",
  "to": "2026-10-22",
  "timezone": "Asia/Taipei",
  "dataStatus": "ok",
  "totals": {
    "pageviews": 4820,
    "uniqueVisitors": 1940,
    "sessions": 2310,
    "clicks": 412,
    "formSubmits": 38,
    "socialClicks": 185
  },
  "previousPeriod": {
    "from": "2026-08-24",
    "to": "2026-09-22",
    "totals": {
      "pageviews": 4200,
      "uniqueVisitors": 1750,
      "sessions": 2050,
      "clicks": 360,
      "formSubmits": 32,
      "socialClicks": 160
    }
  },
  "trends": {
    "pageviews": 15,
    "uniqueVisitors": 11,
    "sessions": 13,
    "clicks": 14,
    "formSubmits": 19,
    "socialClicks": 16
  },
  "daily": [
    {
      "date": "2026-10-22",
      "pageviews": 168,
      "uniqueVisitors": 72,
      "sessions": 84,
      "clicks": 15,
      "formSubmits": 2,
      "socialClicks": 6
    }
  ],
  "devices": {
    "mobile": 1320,
    "desktop": 540,
    "tablet": 80
  },
  "topSources": [
    {
      "name": "google",
      "value": 980
    },
    {
      "name": "instagram",
      "value": 540
    },
    {
      "name": "chatgpt",
      "value": 112
    }
  ],
  "topUtm": [
    {
      "name": "october_special",
      "value": 210
    }
  ],
  "topButtons": [
    {
      "name": "Order Now",
      "value": 196
    }
  ],
  "topCountries": [
    {
      "name": "TW",
      "value": 1620
    },
    {
      "name": "US",
      "value": 210
    }
  ]
}

Analytics pages

GET/sites/{id}/analytics/pages
betaanalytics:viewheavy (20/minute per token, plus 20/minute per site)

Get per-page traffic, entry sessions, bounce rate, engagement duration, button clicks, form submissions, AI assistant referral entries, and cross-tool ids (websitePageId for pages.*, productId for products.*, postId for posts.*) for the selected period. Errors: FORBIDDEN, VALIDATION, RATE_LIMITED (per-site analytics limit), ANALYTICS_BUSY.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • daysinteger · query

    Number of completed calendar days ending yesterday in the website's timezone (1 to 3650, defaults to 30; days=1 means yesterday; ignored when from and to are provided).

  • fromstring · query

    Start calendar date (YYYY-MM-DD) in the website's timezone, inclusive. Must be paired with to.

  • tostring · query

    End calendar date (YYYY-MM-DD) in the website's timezone, inclusive (up to yesterday in site timezone). Must be paired with from.

Response 200

  • daysintegerrequired

    Number of days in the selected range.

  • fromstringrequired

    Start date (YYYY-MM-DD) in the website's timezone.

  • tostringrequired

    End date (YYYY-MM-DD) in the website's timezone.

  • timezonestringrequired

    IANA timezone used for day boundaries.

  • pagesobject[]required
  • pages[].pageIdstringrequired

    Analytics PageRef identifier (e.g. WebsitePage id, 'product:<productId>', 'blog-post:<postId>', or 'blog-index').

  • pages[].kindstringrequired

    Content kind (page, blog-post, product, shop-index, etc.).

  • pages[].websitePageIdstring | nullrequired

    Corresponding WebsitePage id for use with pages.get / pages.update / pages.replace_sections (null for dynamic blog posts or taxonomy pages).

  • pages[].productIdstring | nullrequired

    Corresponding Product id for use with products.get / products.update when kind is 'product' (null otherwise).

  • pages[].postIdstring | nullrequired

    Corresponding BlogPost id for use with posts.get / posts.update when kind is 'blog-post' (null otherwise).

  • pages[].pathstring | nullrequired

    URL path snapshot.

  • pages[].titlestring | nullrequired

    Page title snapshot.

  • pages[].pageviewsintegerrequired

    Total pageviews on this page.

  • pages[].uniqueVisitorsintegerrequired

    Sum of daily unique visitors on this page.

  • pages[].entrySessionsintegerrequired

    Sessions that started on this page.

  • pages[].bounceRateintegerrequired

    Bounce percentage (0 to 100).

  • pages[].avgEngagementSecintegerrequired

    Average foreground engagement time in seconds, weighted by daily pageviews.

  • pages[].ctaClicksintegerrequired

    Custom CTA button clicks on this page.

  • pages[].formSubmitsintegerrequired

    Non-spam form submissions on this page.

  • pages[].aiReferralEntriesintegerrequired

    Entry sessions on this page attributed to AI assistants (ChatGPT, Perplexity, Claude, Gemini, Copilot).

Errors

  • FORBIDDEN 403
  • VALIDATION 400
  • RATE_LIMITED 429 · per-site analytics limit
  • ANALYTICS_BUSY 429

MCP tool analytics_pages

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/analytics/pages?days=30" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "days": 30,
  "from": "2026-09-23",
  "to": "2026-10-22",
  "timezone": "Asia/Taipei",
  "pages": [
    {
      "pageId": "pg_example456",
      "kind": "page",
      "websitePageId": "pg_example456",
      "productId": null,
      "postId": null,
      "path": "/",
      "title": "Home",
      "pageviews": 2840,
      "uniqueVisitors": 1420,
      "entrySessions": 1280,
      "bounceRate": 34,
      "avgEngagementSec": 52,
      "ctaClicks": 245,
      "formSubmits": 22,
      "aiReferralEntries": 36
    }
  ]
}

Analytics bots

GET/sites/{id}/analytics/bots
betaanalytics:viewheavy (20/minute per token, plus 20/minute per site)

Get AI crawler and search bot activity summary (GPTBot, ClaudeBot, PerplexityBot, Googlebot, etc.) for the selected period, with optional per-page intent breakdown (breakdown='page', up to 3650 days) or per-page × per-bot breakdown (breakdown='page_bot', retained for 90 days). Breakdown rows are paged: pass limit and cursor (nextCursor) while hasMore is true. Errors: FORBIDDEN, VALIDATION (details.reason: UNKNOWN_BOT or RANGE_BEFORE_RETENTION), RATE_LIMITED (per-site analytics limit), ANALYTICS_BUSY, INVALID_CURSOR.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • daysinteger · query

    Number of completed calendar days ending yesterday in the website's timezone (1 to 3650, defaults to 30; days=1 means yesterday; ignored when from and to are provided).

  • fromstring · query

    Start calendar date (YYYY-MM-DD) in the website's timezone, inclusive. Must be paired with to.

  • tostring · query

    End calendar date (YYYY-MM-DD) in the website's timezone, inclusive (up to yesterday in site timezone). Must be paired with from.

  • breakdown"none" | "page" | "page_bot" · query

    Optional breakdown mode: 'none' (default, top bots only), 'page' (per-page intent rollup, up to 3650 days), or 'page_bot' (per-page × per-bot rollup, retained for 90 days).

  • pageRefstring · query

    Optional PageRef filter when breakdown is 'page' or 'page_bot' (e.g. a page id, 'blog-post:<id>', 'product:<id>', or 'other').

  • botTokenstring · query

    Optional bot token filter (must be one of the 35 registered tokens, e.g. GPTBot, ClaudeBot, PerplexityBot). Applies to totals, bots, and breakdown='page_bot'; breakdown='page' rows always sum all bots by intent.

  • limitinteger · query

    Maximum number of items to return, 1–100. Defaults to 100.

  • cursorstring · query

    Opaque cursor from the previous page's nextCursor. Omit for the first page.

Response 200

  • daysintegerrequired

    Number of days in the selected range.

  • fromstringrequired

    Start date (YYYY-MM-DD) in the website's timezone.

  • tostringrequired

    End date (YYYY-MM-DD) in the website's timezone.

  • timezonestringrequired

    IANA timezone used for day boundaries.

  • totalsobjectrequired
  • totals.totalHitsintegerrequired

    Total crawler hits in the period.

  • totals.blockedHitsintegerrequired

    Crawler hits blocked by site rules.

  • totals.verifiedHitsintegerrequired

    Hits verified against official bot CIDR/ASN IP ranges.

  • totals.spoofedHitsintegerrequired

    Hits claiming a bot User-Agent that failed official CIDR/ASN IP verification.

  • botsobject[]required
  • bots[].botTokenstringrequired

    Bot User-Agent token (e.g. GPTBot, ClaudeBot).

  • bots[].operatorstringrequired

    Organization operating the bot (e.g. OpenAI, Anthropic, Google).

  • bots[].intent"training" | "retrieval" | "search"required

    Declared purpose of the crawler.

  • bots[].blockablebooleanrequired

    Whether this crawler can be blocked via site rules.

  • bots[].totalHitsintegerrequired

    Total hits from this bot.

  • bots[].blockedHitsintegerrequired

    Blocked hits from this bot.

  • bots[].verifiedHitsintegerrequired

    Verified hits from this bot.

  • bots[].spoofedHitsintegerrequired

    Spoofed hits claiming this bot token.

  • pageBreakdownobject[]
  • pageBreakdown[].pageRefstringrequired

    Canonical PageRef id (e.g. WebsitePage id, blog-post:<id>, product:<id>, or 'other').

  • pageBreakdown[].pathstring | nullrequired

    Canonical page path (null when pageRef is 'other').

  • pageBreakdown[].titlestring | nullrequired

    Canonical page title (null when pageRef is 'other').

  • pageBreakdown[].retrievalHitsintegerrequired

    Hits from AI search/retrieval crawlers.

  • pageBreakdown[].trainingHitsintegerrequired

    Hits from AI model training crawlers.

  • pageBreakdown[].searchHitsintegerrequired

    Hits from search engine indexing crawlers.

  • pageBreakdown[].blockedHitsintegerrequired

    Hits blocked with HTTP 403.

  • pageBreakdown[].spoofedHitsintegerrequired

    Hits that failed official CIDR/ASN verification.

  • pageBreakdown[].lastSeenAtstring | nullrequired

    ISO-8601 timestamp of the latest crawler hit on this page.

  • pageBotBreakdownobject[]
  • pageBotBreakdown[].pageRefstringrequired

    Canonical PageRef id (e.g. WebsitePage id, blog-post:<id>, product:<id>, or 'other').

  • pageBotBreakdown[].pathstring | nullrequired

    Canonical page path (null when pageRef is 'other').

  • pageBotBreakdown[].titlestring | nullrequired

    Canonical page title (null when pageRef is 'other').

  • pageBotBreakdown[].botTokenstringrequired

    Bot User-Agent token (e.g. GPTBot, ClaudeBot).

  • pageBotBreakdown[].operatorstringrequired

    Organization operating the bot.

  • pageBotBreakdown[].intent"training" | "retrieval" | "search"required

    Declared purpose of the crawler.

  • pageBotBreakdown[].hitsintegerrequired

    Total hits from this bot on this page.

  • pageBotBreakdown[].blockedHitsintegerrequired

    Blocked hits from this bot on this page.

  • pageBotBreakdown[].verifiedHitsintegerrequired

    Verified hits from this bot on this page.

  • pageBotBreakdown[].spoofedHitsintegerrequired

    Spoofed hits claiming this bot token on this page.

  • pageBotBreakdown[].lastSeenAtstring | nullrequired

    ISO-8601 timestamp of the latest hit from this bot on this page.

  • hasMoreboolean

    With a breakdown: true when more breakdown rows exist.

  • nextCursorstring | null

    With a breakdown: cursor for the next breakdown page, or null on the last page.

Errors

  • FORBIDDEN 403
  • VALIDATION 400 · details.reason: UNKNOWN_BOT or RANGE_BEFORE_RETENTION
  • RATE_LIMITED 429 · per-site analytics limit
  • ANALYTICS_BUSY 429
  • INVALID_CURSOR 400

MCP tool analytics_bots

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/analytics/bots?days=30" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "days": 30,
  "from": "2026-09-23",
  "to": "2026-10-22",
  "timezone": "Asia/Taipei",
  "totals": {
    "totalHits": 640,
    "blockedHits": 0,
    "verifiedHits": 590,
    "spoofedHits": 12
  },
  "bots": [
    {
      "botToken": "GPTBot",
      "operator": "OpenAI",
      "intent": "training",
      "blockable": true,
      "totalHits": 310,
      "blockedHits": 0,
      "verifiedHits": 302,
      "spoofedHits": 2
    }
  ]
}

Analytics edge

GET/sites/{id}/analytics/edge
betaanalytics:viewheavy (20/minute per token, plus 20/minute per site)

Get Cloudflare CDN & WAF edge traffic and security summary for the selected period: total requests, mitigated requests, static CDN cache hit rate (Worker SSR/ISR HTML and API routes are recorded as 'dynamic' at the outer CDN layer), saved bytes, edge 4xx/5xx responses (errors4xx includes HTTP 403 WAF/bot blocks and 404 scanner probes), cache status breakdown, top countries, and security actions. Errors: FORBIDDEN, HOSTED_ONLY, VALIDATION, RATE_LIMITED (per-site analytics limit), ANALYTICS_BUSY.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • daysinteger · query

    Number of completed calendar days ending yesterday in the website's timezone (1 to 3650, defaults to 30; days=1 means yesterday; ignored when from and to are provided).

  • fromstring · query

    Start calendar date (YYYY-MM-DD) in the website's timezone, inclusive. Must be paired with to.

  • tostring · query

    End calendar date (YYYY-MM-DD) in the website's timezone, inclusive (up to yesterday in site timezone). Must be paired with from.

Response 200

  • daysintegerrequired

    Number of days in the selected range.

  • fromstringrequired

    Start date (YYYY-MM-DD) in the website's timezone.

  • tostringrequired

    End date (YYYY-MM-DD) in the website's timezone.

  • timezonestringrequired

    IANA timezone used for day boundaries.

  • summaryobjectrequired
  • summary.totalRequestsintegerrequired

    Total edge requests received by Cloudflare.

  • summary.mitigatedRequestsintegerrequired

    Suspicious or attack requests mitigated at the edge (WAF / bot rules).

  • summary.cachedRequestsintegerrequired

    Requests served from outer Cloudflare CDN cache (hit, stale, revalidated).

  • summary.cachedBytesnumberrequired

    Bytes served from outer Cloudflare CDN cache.

  • summary.cacheHitRateintegerrequired

    Outer Cloudflare CDN static cache hit percentage (0 to 100; Worker-rendered SSR/ISR HTML and API routes are recorded as 'dynamic' in cacheStatusBreakdown).

  • summary.errors4xxintegerrequired

    Edge 4xx responses (includes HTTP 403 blocks/challenges from WAF & bot rules and 404 responses to scanner probes).

  • summary.errors5xxintegerrequired

    Edge 5xx responses.

  • cacheStatusBreakdownobject[]

    Breakdown of Cloudflare edge cache statuses (dynamic, hit, miss, etc.).

  • cacheStatusBreakdown[].namestringrequired

    Channel, button, link, or country identifier.

  • cacheStatusBreakdown[].valueintegerrequired

    Count in the selected period.

  • topCountriesobject[]required

    Top request origin countries (ISO 3166-1 alpha-2).

  • topCountries[].namestringrequired

    Channel, button, link, or country identifier.

  • topCountries[].valueintegerrequired

    Count in the selected period.

  • securityActionsobject[]required

    Mitigation actions taken by Cloudflare WAF (block, managed_challenge, etc.).

  • securityActions[].namestringrequired

    Channel, button, link, or country identifier.

  • securityActions[].valueintegerrequired

    Count in the selected period.

Errors

  • FORBIDDEN 403
  • HOSTED_ONLY 409
  • VALIDATION 400
  • RATE_LIMITED 429 · per-site analytics limit
  • ANALYTICS_BUSY 429

MCP tool analytics_edge

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/analytics/edge?days=30" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "days": 30,
  "from": "2026-09-23",
  "to": "2026-10-22",
  "timezone": "Asia/Taipei",
  "summary": {
    "totalRequests": 28400,
    "mitigatedRequests": 142,
    "cachedRequests": 24100,
    "cachedBytes": 512000000,
    "cacheHitRate": 85,
    "errors4xx": 34,
    "errors5xx": 0
  },
  "cacheStatusBreakdown": [
    {
      "name": "hit",
      "value": 24100
    },
    {
      "name": "dynamic",
      "value": 4300
    }
  ],
  "topCountries": [
    {
      "name": "TW",
      "value": 22100
    },
    {
      "name": "US",
      "value": 3200
    }
  ],
  "securityActions": [
    {
      "name": "managed_challenge",
      "value": 98
    },
    {
      "name": "block",
      "value": 44
    }
  ]
}