Skip to content

Reports and stats endpoints ​

These routes return click reports for one short link and site-wide stats for the dashboard. Each entry lists the parameters, response fields and errors.

Use these routes to read click numbers: one short link's report, its chart data, its recent clicks and a CSV download, plus the site-wide stats behind the dashboard. Sign-in, permissions, the response envelope and paging work as in the REST API overview.

All paths are relative to the base URL /wp-json/link-manager-pro/v1. Examples use https://example.com and an Application Password placeholder (USER:APPLICATION_PASSWORD). Inside WordPress, send the X-WP-Nonce header instead.

Every route here needs the permission link_manager_pro_access (Permissions) and answers 200 on success.

bash
curl -u USER:APPLICATION_PASSWORD \
  "https://example.com/wp-json/link-manager-pro/v1/stats/clicks?start=2026-10-01&end=2026-10-23"

How the numbers are counted ​

Read this section once. The entries refer back to it.

Dates and time zones ​

  • Date parameters (start, end) are site-local days written Y-m-d, in the time zone set in WordPress. A value that is not a string, not that exact shape or not a real date (2026-02-31) counts as missing.
  • Click times are stored in UTC. A day boundary means midnight in the site time zone, so a day can be 23 or 25 hours long where clocks change.
  • Chart rows are bucketed by site-local day, using the offset in force at each click.
  • Fields that hold a stored time (clicked_at, first_click_at, last_click_at, created_at) are UTC strings written Y-m-d H:i:s. The CSV export is the exception: it writes site time.

Date ranges ​

Routes that take a range behave in one of two ways.

KindRoutesMissing or invalid datesLimits
Resolved range/stats, /stats/clicks, /stats/heatmap, /stats/countries, /links/{id}/clicks (when you send a date)A missing end is the site's today. A missing start is 30 days ending on end (the end day and the 29 days before it).Reversed dates are swapped. end never goes past the site's today. The span is at most 7305 days (20 years); an older start is moved up silently.
Open range/links/{id}/report, /links/{id}/report/exportA missing or invalid side has no bound. Neither date means all time.No cap and no swap. A start after end matches no clicks.

GET /links/{id}/clicks with neither start nor end is all time: it starts on the site-local day of the earlier of the link's creation and its first click, and ends on the site's today.

Which clicks count ​

  • Site-wide routes count recorded clicks on short links. Clicks on the hidden links behind redirects, and internal-link clicks, are left out.
  • Per-link routes (/links/{id}/...) count every recorded click of that link ID, including the ID of a redirect's hidden link.
  • A click is recorded only while click tracking is on. When bot detection is on, requests the tracker filters out (bots and blocked IP addresses) are not recorded, so they never appear here.
  • Old clicks are removed by the click retention setting, so totals cover the kept history.

Caching ​

WhatCache
GET /links/{id}/report (entity, summary, breakdowns, recent)Cached as a transient for the setting report_cache_ttl in the Advanced group (default 600 seconds, 0 to 86400; 0 turns the cache off). The link_manager_pro_report_cache_ttl filter can change it. The key follows the date bounds, the link's updated_at and a report generation number that most writes bump.
GET /stats (range, previous, all_time, and the totals)Cached for 60 seconds per range. window, site, health.last_scan and the tracking fields are never cached.
GET /stats/top, GET /stats/linksCached for 60 seconds per type and limit.
Other routesRead live.

A cache entry is dropped at once when a link, affiliate, redirect or link-health write happens, or a click purge or backup restore runs.

Short addresses ​

Fields named short_url hold the public address the plugin builds: the site URL, a prefix and the slug. Which prefix applies is explained under Affiliate link prefix.

Breakdown and click objects ​

The breakdown item ​

Report breakdowns are arrays of items, most clicks first, ties by label without regard to case.

FieldTypeWhat it holds
labelstringThe group name.
countintegerClicks in that group.

The recent click object ​

recent in the report and each row of the recent-clicks route share one shape.

FieldTypeWhat it holds
clicked_atstringWhen the click happened, UTC, Y-m-d H:i:s.
is_uniquebooleanWhether the click was the visitor's first.
post_idintegerThe post the click came from. 0 when none.
devicestringDesktop, Mobile, Tablet or Other, from the user agent.
osstringThe OS family, for example Windows, macOS, iOS, Android, Linux or Other.
browserstringThe browser family, for example Chrome, Firefox, Edge, Opera, Samsung Internet or Other.
referrer_domainstring or nullThe referring host, when stored.
referrer_urlstring or nullThe referring URL, when stored.
country_codestring or nullThe two-letter country code. null when empty.
post_titlestring or nullThe plain-text title of the post, or Post #ID when it has no title or no longer exists. null when post_id is 0.

GET /links/{id}/clicks

Returns one row per day with total and unique clicks, for the chart of one short link.

Permission: link_manager_pro_access (Permissions)

Path parameters:

NameTypeWhat it is
idintegerThe short link ID.

Query parameters:

NameTypeRequiredDefaultWhat it does
startstringNoall timeFirst day, Y-m-d, site-local. See Date ranges.
endstringNothe site's todayLast day, Y-m-d, site-local.

Response: 200. data is an array with one item per day in the range, oldest first. Days without clicks are included with zeros.

FieldTypeWhat it holds
datestringThe site-local day, Y-m-d.
totalintegerClicks that day.
uniqueintegerUnique clicks that day.
json
{
  "success": true,
  "data": [
    { "date": "2026-10-21", "total": 4, "unique": 3 },
    { "date": "2026-10-22", "total": 0, "unique": 0 }
  ]
}

Errors:

StatusWhen
404No short link has that ID.

GET /links/{id}/report

Returns the totals, breakdowns and newest clicks of one short link for an optional date range.

Permission: link_manager_pro_access (Permissions)

Path parameters:

NameTypeWhat it is
idintegerThe short link ID.

Query parameters:

NameTypeRequiredDefaultWhat it does
startstringNono boundFirst day, Y-m-d, site-local. An empty or invalid value counts as missing.
endstringNono boundLast day, Y-m-d, site-local. The whole day is included.

Response: 200. data holds:

FieldTypeWhat it holds
entityobjectThe link and live extras, fields below.
summaryobjectTotals for the range, fields below.
breakdownsobjectClick groups for the range, fields below.
recentarrayUp to 20 newest clicks in the range, newest first by ID. Each is a recent click object.
trackingobjectTracking settings that affect how to read the numbers, fields below.

entity:

FieldTypeWhat it holds
typestringAlways link.
idintegerThe link ID.
namestringThe slug.
slugstringThe slug.
urlstringThe destination URL.
forward_paramsbooleanWhether the visitor's query string passes on to the destination.
created_atstring or nullWhen the link was created, UTC, Y-m-d H:i:s.
short_urlstringThe public short address (live, not cached).
lifetime_clicksintegerThe link's lifetime click counter. Ignores the date range and can differ from summary.clicks.
placed_inintegerHow many published posts have content that links to this short link.
rankobject or nullWhere the lifetime counter ranks: position (1 is most, ties share it), total (all links) and share (percent of all lifetime clicks, one decimal).

summary:

FieldTypeWhat it holds
clicksintegerClicks in the range.
unique_clicksintegerUnique clicks.
qualified_clicksintegerClicks that came from a post (post_id above 0).
conversion_labelstringAlways Qualified Clicks.
first_click_atstring or nullEarliest click in the range, UTC. null with no clicks.
last_click_atstring or nullLatest click in the range, UTC. null with no clicks.

breakdowns (each list holds at most 10 breakdown items unless noted):

FieldTypeWhat it holds
devicearrayClicks by device type.
osarrayClicks by OS family.
browserarrayClicks by browser family.
countryarrayClicks by country code. An empty code is labeled Unknown.
referrerarrayClicks by referring host. An empty host is labeled Direct.
utmobjectsource, medium and campaign arrays of breakdown items (top 10 of the inbound UTM values), and totals with the integer count of all tagged clicks for each of the three.
sourceobjectcontent (from a post on this site), site (from another page of this site, such as a menu, widget, the home page or an archive), referral (another site) and direct (no referrer). Integers that add up to clicks.
postsarrayTop 10 posts sending clicks. Each item has post_id (integer), label (the title) and count (integer).
sitesarrayTop 10 referring hosts for clicks not sent from a post. This site's own host is left out.

Device, OS and browser are counted from the 2000 most frequent distinct user agents.

tracking:

FieldTypeWhat it holds
tracking_enabledbooleanWhether click tracking is on.
retention_daysintegerDays of click history kept. 0 keeps it forever.
autolink_site_enabledbooleanWhether auto-linking is on for the site.
history_trustedbooleanWhether the last 90 days were fully recorded.
history_reasonstringWhy not, when history_trusted is false: tracking_off, retention_short, tracking_resumed, retention_changed, clicks_restored or gap. Empty string when trusted.
json
{
  "success": true,
  "data": {
    "entity": {
      "type": "link",
      "id": 12,
      "name": "spring-sale",
      "slug": "spring-sale",
      "url": "https://example.com/shop/spring",
      "forward_params": false,
      "created_at": "2026-09-30 09:15:00",
      "short_url": "https://example.com/link/spring-sale",
      "lifetime_clicks": 240,
      "placed_in": 3,
      "rank": { "position": 2, "total": 48, "share": 12.5 }
    },
    "summary": {
      "clicks": 31,
      "unique_clicks": 24,
      "qualified_clicks": 18,
      "conversion_label": "Qualified Clicks",
      "first_click_at": "2026-10-01 07:02:11",
      "last_click_at": "2026-10-22 18:40:03"
    },
    "breakdowns": {
      "device": [{ "label": "Desktop", "count": 20 }],
      "os": [{ "label": "Windows", "count": 14 }],
      "browser": [{ "label": "Chrome", "count": 19 }],
      "country": [{ "label": "US", "count": 17 }],
      "referrer": [{ "label": "Direct", "count": 13 }],
      "utm": {
        "source": [{ "label": "newsletter", "count": 5 }],
        "medium": [],
        "campaign": [],
        "totals": { "source": 5, "medium": 0, "campaign": 0 }
      },
      "source": { "content": 18, "site": 3, "referral": 4, "direct": 6 },
      "posts": [{ "post_id": 77, "label": "Spring picks", "count": 12 }],
      "sites": [{ "label": "news.example.org", "count": 4 }]
    },
    "recent": [
      {
        "clicked_at": "2026-10-22 18:40:03",
        "is_unique": true,
        "post_id": 77,
        "device": "Desktop",
        "os": "Windows",
        "referrer_domain": "example.com",
        "referrer_url": "https://example.com/spring-picks/",
        "browser": "Chrome",
        "country_code": "US",
        "post_title": "Spring picks"
      }
    ],
    "tracking": {
      "tracking_enabled": true,
      "retention_days": 0,
      "autolink_site_enabled": true,
      "history_trusted": true,
      "history_reason": ""
    }
  }
}

Errors:

StatusWhen
404No short link has that ID. The WordPress error code is link_not_found and the message is "Link not found".

GET /links/{id}/report/export

Downloads every recorded click of one short link as a CSV file, newest first.

Permission: link_manager_pro_access (Permissions)

Path parameters:

NameTypeWhat it is
idintegerThe short link ID.

Query parameters:

NameTypeRequiredDefaultWhat it does
startstringNono boundFirst day, Y-m-d, site-local. An empty, malformed or impossible date counts as missing.
endstringNono boundLast day, Y-m-d, site-local. The whole day is included.

Response: 200. The body is a CSV file, not the JSON envelope. The response sends these headers:

HeaderValue
Content-Typetext/csv; charset=utf-8
Content-Dispositionattachment; filename="link-manager-pro-report-SLUG-YYYY-MM-DD.csv". SLUG is the link slug made safe for a file name. The date is the site's today.
Cache-Controlno-cache, no-store, must-revalidate

The first row holds these column names. Each later row is one click, newest first (by click time, then ID). The file is streamed 500 rows at a time and has no paging parameters.

ColumnWhat it holds
Clicked AtThe click time in site time, Y-m-d H:i:s.
Link SlugThe link's slug.
Target URLThe destination URL recorded for the click.
CountryThe two-letter country code, or empty.
Referrer DomainThe referring host, or empty.
Referrer URLThe referring URL, or empty.
DeviceDesktop, Mobile, Tablet or Other.
OSThe OS family.
BrowserThe browser family.
Uniqueyes or no.
Post IDThe post the click came from, or empty.
UTM SourceThe inbound utm_source value, or empty.
UTM MediumThe inbound utm_medium value, or empty.
UTM CampaignThe inbound utm_campaign value, or empty.
UTM TermThe inbound utm_term value, or empty.
UTM ContentThe inbound utm_content value, or empty.

A cell that starts with =, +, -, @, a tab or a carriage return gets a leading single quote, so spreadsheets do not run it as a formula.

bash
curl -u USER:APPLICATION_PASSWORD -o clicks.csv \
  "https://example.com/wp-json/link-manager-pro/v1/links/12/report/export?start=2026-10-01"
text
Clicked At,"Link Slug","Target URL",Country,"Referrer Domain","Referrer URL",Device,OS,Browser,Unique,"Post ID","UTM Source","UTM Medium","UTM Campaign","UTM Term","UTM Content"
"2026-10-22 18:40:03",spring-sale,https://example.com/shop/spring,US,example.com,https://example.com/spring-picks/,Desktop,Windows,Chrome,yes,77,newsletter,,,,

Errors:

StatusWhen
404No short link has that ID. The error comes before any CSV is sent.

GET /links/{id}/report/recent

Returns a page of the newest clicks of one short link, with no date filter.

Permission: link_manager_pro_access (Permissions)

Path parameters:

NameTypeWhat it is
idintegerThe short link ID.

Query parameters:

NameTypeRequiredDefaultWhat it does
pageintegerNo1The page to return. See Pagination.
per_pageintegerNo10Rows per page, kept between 1 and 100. When you send the parameter, a missing, empty, zero, negative or non-numeric value gives the default 10. The cap of 100 stays.

Response: 200. data is a page object (Pagination). Each row of data.data is a recent click object. Rows are ordered newest first by click ID.

json
{
  "success": true,
  "data": {
    "current_page": 1,
    "data": [
      {
        "clicked_at": "2026-10-22 18:40:03",
        "is_unique": true,
        "post_id": 0,
        "device": "Mobile",
        "os": "iOS",
        "referrer_domain": null,
        "referrer_url": null,
        "browser": "Safari",
        "country_code": "DE",
        "post_title": null
      }
    ],
    "per_page": 10,
    "total": 31,
    "last_page": 4
  }
}

The example shows part of the page object. The other page fields are listed in the REST API overview.

Errors:

StatusWhen
404No short link has that ID.

Site-wide stats ​

Get the dashboard stats ​

GET /stats

Returns the dashboard numbers: all-time totals, the click KPIs for a date range and the previous period, link health counts and the site calendar.

Permission: link_manager_pro_access (Permissions)

Query parameters:

NameTypeRequiredDefaultWhat it does
startstringNo30 days ending on endFirst day, Y-m-d, site-local. See Date ranges.
endstringNothe site's todayLast day, Y-m-d, site-local.

Response: 200. data holds:

FieldTypeWhat it holds
totalLinksintegerShort links, not counting the hidden links behind redirects.
totalClicksintegerAll recorded short-link clicks.
uniqueClicksintegerUnique recorded short-link clicks.
brokenCountintegerActive link health issues (content plus traffic).
notFoundCountintegerActive traffic issues, which are visitor 404s.
rangeobjectClick KPIs for the resolved range, fields below.
previousobjectThe same KPIs for the equal-length period right before start.
all_timeobjectAll-time totals, fields below.
healthobjectcontent (integer), traffic (integer), traffic_24h (integer, distinct 404 pages seen in the last 24 hours) and last_scan.
windowobjectThe resolved range: start, end (strings), days (integer) and previous with the same three fields.
siteobjecttoday (string Y-m-d), presets, timezone (string) and startOfWeek (integer, 0 is Sunday).

health.last_scan is null until a link health scan has finished. Otherwise it holds posts, checked, unchecked and started_at (integers) and finished_at (string).

site.presets has the keys 7d, 14d and 30d. Each holds the same fields as window, resolved against the site's today.

range:

FieldTypeWhat it holds
start, endstringThe resolved days, Y-m-d.
daysintegerDays in the range, both ends included.
clicksintegerShort-link clicks in the range.
uniqueintegerUnique clicks in the range.
from_postsintegerClicks that came from a post.
partner_clicksintegerClicks on short links that go to an affiliate's domain.
links_totalintegerShort links, not counting the hidden redirect links.

previous holds start, end, days (the previous period, as in window.previous), clicks, unique, from_posts and partner_clicks.

all_time:

FieldTypeWhat it holds
clicks_todayintegerClicks since midnight, site time.
clicksintegerAll recorded short-link clicks.
uniqueintegerUnique clicks.
unique_sharenumberUnique clicks as a percent of clicks, one decimal.
partner_clicksintegerClicks on short links to affiliate domains.
partner_sharenumberPartner clicks as a percent of clicks, one decimal.
partners_totalintegerAffiliates.
partners_activeintegerAffiliates with at least one click.
partner_linksintegerShort links that go to an affiliate domain.
autolink_linksintegerShort links with auto-linking on.
autolink_partnersintegerAffiliates with auto-linking on.
links_totalintegerShort links, not counting the hidden redirect links.
redirect_hitsintegerHits on redirects.
internal_clicksinteger or nullInternal-link clicks. null unless click tracking and internal-link tracking are both on.
lifetime_clicksintegerThe sum of the links' lifetime counters.
tracking_enabledbooleanWhether click tracking is on.
retention_daysintegerDays of click history kept. 0 keeps it forever.
autolink_site_enabledbooleanWhether auto-linking is on for the site.
history_trustedbooleanWhether the last 90 days were fully recorded.
history_reasonstringThe reason when not trusted, as in the report's tracking object.
json
{
  "success": true,
  "data": {
    "totalLinks": 48,
    "totalClicks": 1520,
    "uniqueClicks": 1104,
    "brokenCount": 3,
    "notFoundCount": 1,
    "range": {
      "start": "2026-09-24", "end": "2026-10-23", "days": 30,
      "clicks": 410, "unique": 301, "from_posts": 255,
      "partner_clicks": 96, "links_total": 48
    },
    "previous": {
      "start": "2026-08-25", "end": "2026-09-23", "days": 30,
      "clicks": 380, "unique": 280, "from_posts": 240, "partner_clicks": 88
    },
    "all_time": {
      "clicks_today": 7, "clicks": 1520, "unique": 1104, "unique_share": 72.6,
      "partner_clicks": 410, "partner_share": 27.0, "partners_total": 5,
      "partners_active": 4, "partner_links": 12, "autolink_links": 9,
      "autolink_partners": 3, "links_total": 48, "redirect_hits": 62,
      "internal_clicks": null, "lifetime_clicks": 1530,
      "tracking_enabled": true, "retention_days": 0,
      "autolink_site_enabled": true, "history_trusted": true, "history_reason": ""
    },
    "health": {
      "content": 2, "traffic": 1, "traffic_24h": 1,
      "last_scan": { "posts": 120, "finished_at": "2026-10-22 03:10:00", "checked": 640, "unchecked": 0, "started_at": 1792638000 }
    },
    "window": {
      "start": "2026-09-24", "end": "2026-10-23", "days": 30,
      "previous": { "start": "2026-08-25", "end": "2026-09-23", "days": 30 }
    },
    "site": {
      "today": "2026-10-23",
      "presets": { "7d": {}, "14d": {}, "30d": {} },
      "timezone": "Europe/Berlin",
      "startOfWeek": 1
    }
  }
}

In the example, each presets entry is shortened to {}. The code fills it with the window fields.

Errors: None specific to this route.

List the top partners ​

GET /stats/affiliates

Returns up to 10 affiliates with the most recorded clicks on short links that go to their domain.

Permission: link_manager_pro_access (Permissions)

Query parameters: None.

Response: 200. data is an array of at most 10 items, most clicks first. Ties go to the older affiliate (lower ID). Affiliates with no clicks are included while there are fewer than 10.

FieldTypeWhat it holds
idintegerThe affiliate ID.
site_namestringThe affiliate's name.
domainstringThe affiliate's domain.
click_countintegerRecorded clicks on short links to that domain, all time. It is not the stored counter on the affiliate.
enable_autolinkbooleanWhether auto-linking uses this affiliate.
json
{
  "success": true,
  "data": [
    { "id": 3, "site_name": "Example Store", "domain": "store.example.com", "click_count": 210, "enable_autolink": true }
  ]
}

Errors: None specific to this route.

Get the site clicks series ​

GET /stats/clicks

Returns one row per day with total and unique short-link clicks for the chart on the dashboard.

Permission: link_manager_pro_access (Permissions)

Query parameters:

NameTypeRequiredDefaultWhat it does
startstringNo30 days ending on endFirst day, Y-m-d, site-local. See Date ranges.
endstringNothe site's todayLast day, Y-m-d, site-local.

Response: 200. data is an array with one item per day, oldest first, with zeros for quiet days. Each item has the fields of the short link series: date, total and unique.

json
{
  "success": true,
  "data": [
    { "date": "2026-10-22", "total": 9, "unique": 7 },
    { "date": "2026-10-23", "total": 7, "unique": 5 }
  ]
}

Errors: None specific to this route.

Get clicks by country ​

GET /stats/countries

Returns short-link clicks grouped by country code, for the geo map.

Permission: link_manager_pro_access (Permissions)

Query parameters:

NameTypeRequiredDefaultWhat it does
startstringNo30 days ending on endFirst day, Y-m-d, site-local. See Date ranges. The route never returns all time.
endstringNothe site's todayLast day, Y-m-d, site-local.

Response: 200. data holds:

FieldTypeWhat it holds
rowsarrayCountries, most clicks first. Each item has code (string, upper-case two letters) and total (integer).
totalintegerAll clicks in the range, including the unresolved ones.
unresolvedintegerClicks with an empty code, the unknown code XX or a code that is not two letters. They have no row.
json
{
  "success": true,
  "data": {
    "rows": [{ "code": "US", "total": 190 }, { "code": "DE", "total": 64 }],
    "total": 270,
    "unresolved": 16
  }
}

Errors: None specific to this route.

Get the click heatmap ​

GET /stats/heatmap

Returns short-link clicks grouped by weekday and hour, in site time, for the dashboard heatmap.

Permission: link_manager_pro_access (Permissions)

Query parameters:

NameTypeRequiredDefaultWhat it does
startstringNo30 days ending on endFirst day, Y-m-d, site-local. See Date ranges.
endstringNothe site's todayLast day, Y-m-d, site-local.

Response: 200. data holds:

FieldTypeWhat it holds
cellsarrayOnly the cells that have clicks. Each cell is [hour, weekday, count]: hour is 0 to 23, weekday is 0 (Monday) to 6 (Sunday).
maxintegerThe largest cell count.
totalintegerAll clicks in the cells.
by_dayarray of 7 integersClicks per weekday, Monday first.
by_hourarray of 24 integersClicks per hour, midnight first.
busiestobject or nullnull when total is 0. Otherwise days and hours, each with from and to (inclusive bucket indexes; to below from means the span wraps past Sunday or 23:00), clicks (integer) and share (percent of all clicks, one decimal).

A busiest span starts at the peak and grows to a neighbor that has at least 75 percent of the peak. It spans at most 3 weekdays or 3 hours.

json
{
  "success": true,
  "data": {
    "cells": [[9, 1, 14], [10, 1, 22]],
    "max": 22,
    "total": 36,
    "by_day": [0, 36, 0, 0, 0, 0, 0],
    "by_hour": [0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    "busiest": {
      "days": { "from": 1, "to": 1, "clicks": 36, "share": 100.0 },
      "hours": { "from": 9, "to": 10, "clicks": 36, "share": 100.0 }
    }
  }
}

Errors: None specific to this route.

GET /stats/links

Returns the short links with the most recorded clicks. The wp-admin dashboard widget reads the same list.

Permission: link_manager_pro_access (Permissions)

Query parameters:

NameTypeRequiredDefaultWhat it does
limitintegerNo5How many links to return. A value of 0 or less, or one that is not a number, gives 5. A value above 100 is cut to 100.

Response: 200. data is an array, most clicks first and newest link first on ties. Links with no recorded click and the hidden redirect links are left out. The list is cached for 60 seconds per limit.

FieldTypeWhat it holds
idintegerThe link ID.
slugstringThe slug.
target_urlstringThe destination URL.
click_countintegerRecorded clicks in the kept history. It is not the lifetime counter.
json
{
  "success": true,
  "data": [
    { "id": 12, "slug": "spring-sale", "target_url": "https://example.com/shop/spring", "click_count": 240 }
  ]
}

Errors: None specific to this route.

List the top posts ​

GET /stats/posts

Returns up to 10 posts that sent the most short-link clicks.

Permission: link_manager_pro_access (Permissions)

Query parameters: None.

Response: 200. data is an array, most clicks first. Redirect hits and internal-link clicks do not count. Posts that no longer exist are left out by the query, so it returns 10 posts whenever 10 existing posts sent clicks.

FieldTypeWhat it holds
post_idintegerThe post ID.
post_titlestringThe post's stored title.
click_countintegerClicks sent from that post, all time.
statusstring or nullA label such as "Draft", or null for a public post.
urlstring or nullThe permalink. null for a post that isn't public or private.
edit_urlstring or nullThe edit link. null for a trashed post.
json
{
  "success": true,
  "data": [
    {
      "post_id": 77,
      "post_title": "Spring picks",
      "click_count": 132,
      "status": null,
      "url": "https://example.com/spring-picks/",
      "edit_url": "https://example.com/wp-admin/post.php?post=77&action=edit"
    }
  ]
}

Errors: None specific to this route.

Get a top list ​

GET /stats/top

Returns the ranked rows for one "What's working" list: short links, campaigns, partners or posts, all time.

Permission: link_manager_pro_access (Permissions)

Query parameters:

NameTypeRequiredDefaultWhat it does
typestringYesnonelinks, campaigns, partners or posts. Case does not matter and spaces around it are trimmed.
limitintegerNo10Rows to return, kept between 1 and 25. A value below 1 or not a whole number gives 10.

Response: 200. data holds:

FieldTypeWhat it holds
typestringThe list that was asked for.
totalintegerHow many items the list ranks: all short links, all campaigns, all partners, or posts with at least one click.
clicks_totalintegerAll recorded short-link clicks, for working out each row's share.
rowsarrayLargest first. Items with no clicks are left out. Fields depend on type, below.

Rows for links: id (integer), slug, short_url, target_url (strings) and clicks (integer).

Rows for campaigns: slug, name (strings), managed (boolean), link_count, clicks and unique_clicks (integers). They come from the first page of the campaign list, sorted by total clicks.

Rows for partners: id (integer), name, domain (strings), clicks, unique_clicks and link_count (integers). Ties go to the lower ID.

Rows for posts: post_id (integer), title (string, empty when the post is gone), exists (boolean), status (string or null, WordPress's label for a status such as Draft, null for a public post or a missing one), url (string or null, only for a public or private post), edit_url (string or null, never for a trashed or deleted post) and clicks (integer). Ties go to the lower post ID.

The list is cached for 60 seconds per type and limit.

json
{
  "success": true,
  "data": {
    "type": "links",
    "total": 48,
    "clicks_total": 1520,
    "rows": [
      {
        "id": 12,
        "slug": "spring-sale",
        "short_url": "https://example.com/link/spring-sale",
        "target_url": "https://example.com/shop/spring",
        "clicks": 240
      }
    ]
  }
}

Errors:

StatusWhen
422type is missing or not one of the four values. The error is on the field type: "Choose links, campaigns, partners or posts."