Tracking and conversions
What a link actually measures, where those numbers live, and how it closes.
The API tells you whether a link is still open; only the Dashboard shows how it performs.
The API has no counters
GET /links/{id} returns what the link is, never how it has performed: no views, conversions
or revenue.
https://api.wajub.com/links/{id}curl https://api.wajub.com/links/8kD2xQpLm \
-H "Authorization: sk.xxxxxxxxxxxxxxxx…"The answer is the link's state, which is what you poll to know whether it is still collecting.
Listing works the same way. It takes per_page, search, archived to see archived links instead
of live ones, only_public, type (product, event, fundraising or donation), and
sort_by (created_at, updated_at, title or type) with sort_dir (desc or asc). The
list follows the sort first, then the newest first among links that tie. For exports, a cursor
walks the list in its default order, newest first: with another sort the list is paged by number
and carries no cursor. A type, sort_by or sort_dir outside these values is a 422 on that
field, as a per_page out of range is.
https://api.wajub.com/linksWhat is actually measured
Every visit that gets past the access gates is counted, with where it came from (the HTTP referrer), the visitor's country and their device type.
Unique visitors are counted per day, so the same person visiting on two days counts as two unique visitors. Read the figure as "unique per day", not as people.
A blocked visit is not a view
When a link is password-protected, an attempt that fails the password is not counted. Neither is a
visit to a link that is unpublished, expired or past its view limit. The counter only moves for
visits that actually reached the page, which is what makes max_views a usable limit.
The numbers, and where to read them
Links → a link → Overview is the only place these surface. Total Views, Total Sales and Total Revenue count the link's whole life, and Conversion Rate sets those sales against its visitors. The period you pick, the last 7, 14, 30 or 90 days, changes only the charts: the bars under each total and Visits & Sales Trends. The average transaction, views per transaction, top countries and devices always cover the last 30 days.
Conversion rate is per visitor, not per view
The figure is transactions ÷ unique visitors, not transactions ÷ views. A page someone opened
four times before paying counts as one visitor and one conversion, so the rate reads higher than a
per-view calculation would. Compare it against itself over time rather than against a number from
another tool.
Attributing a channel
There is no query parameter that tags a visit. A ?src=whatsapp on the shared URL is carried
nowhere: it does not reach the payment, it is not stored on the view, and it will not appear in any
report.
What you have instead is two things that do work.
The referrer is captured automatically, so traffic that arrives with one, from a link in a post or a page, already shows its origin in the analytics. Traffic from WhatsApp, SMS or a QR code carries no referrer, which is most of the traffic in practice.
So for anything you genuinely need to attribute, make one link per channel. Same product, same
price, different custom_url: wajub.link/cafe-whatsapp, wajub.link/cafe-instagram. Each keeps
its own views, its own conversion rate and its own revenue, and the comparison is exact rather than
inferred.
A payment made on a link names it: its link field is the link's id, in the API and in the
payment.* webhooks, so your handler knows which link, and so which channel, the money came from.
GET /payments has no link filter: to list a link's payments, read Links → a link →
Transactions in the Dashboard, or keep the link of each payment as it arrives.
How a link closes
Four settings end a link's life, and they do not close it in the same way.
| Set | Closes | The payer gets |
|---|---|---|
expiry_date | The page, at a moment you choose | 410, before anything renders |
is_archived | The page, now | 410, before anything renders |
sales_limit | The payment, not the page | 422 on paying, This payment link has reached its sales limit. |
single_use_link | The page, after its first successful payment | A page saying the link has already been used to pay |
The difference matters. An expired or archived link never opens: the payer sees a closed page and that is the end of it. A link at its sales limit still opens normally, shows the product and the button, and only refuses when they try to pay. If you are selling a fixed quantity, expect payers to reach that message rather than a closed page.
A single-use link takes one payer at a time. While someone is paying through it, another payer is
told that a payment through the link is in progress, and that the link opens again if that payment
does not go through. Once a payment succeeds, the link stays closed, even if you refund it. No field
of the link says it is closed: payment.succeeded, whose link is the link's id, is your signal.
Should a second payment still succeed through it, such as an earlier attempt the operator confirms
late, your team's owner, administrators and finance members get an e-mail naming the payment to
refund: Wajub does not refund it on its own.
link.expired is sent once, within a day after a link's expiry_date passes, unless the link is
archived by then, with the link in data. Archiving sends link.updated, and so does a sale that
changes a product's stock. Reaching the sales limit and closing a single-use link send no event of
their own.
Archiving is the reversible one: set is_archived back to false through PUT /links/{id} and the
link collects again, keeping everything it already gathered. expiry_date is a condition rather
than a state, so moving it forward reopens a link that had closed on it.
Unpublishing with is_public: false also closes a link, but answers 404 rather than 410, since
an unpublished link is meant to look like it never existed. The access gates are covered in
Customization.
Reconciling the money
A link's payments are ordinary payments. They arrive in your Payments list, fire
payment.succeeded, settle into your balance and refund like any other, so there is nothing
link-specific to reconcile.
What the webhook carries is whatever the payer typed into your extra_fields, nested under
metadata.extra_fields, and the link the payment came from.
Related pages
- Payment LinksWhat the product is, and when a link beats an integration.
- QuickstartCreate a link, publish it, share it.
- CustomizationImages, languages, currencies, and who is allowed in.
- WebhooksListen for payment.succeeded and fulfil automatically.
- Payment Links API referenceEvery field on the resource, and the five endpoints.