Skip to content

SEO traffic (CTR)

POST /v1/traffic/clicks runs real Google searches from genuine browsers, finds your target URL in the results, and clicks it — then browses with natural dwell. Use it to test organic CTR, dwell time, and search visibility. Billed $0.04 per delivered click.

Terminal window
curl -X POST https://api.serplify.io/v1/traffic/clicks \
-H "Authorization: Bearer live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme — running shoes cluster",
"keywords": [
"best running shoes",
"trail running shoes",
"cheap running shoes"
],
"target": "example.com",
"quantity": 200,
"geo": { "country": "US" },
"device": "mobile",
"search_max_pages": 5,
"dwell_seconds_min": 40,
"dwell_seconds_max": 120,
"pages_per_visit": 2
}'
FieldTypeRequiredDefaultNotes
keywordsstring[] | object[]yes*Up to 50 queries in one campaign. Strings split quantity evenly; objects { keyword, quantity } set each share explicitly.
keywordstringyes*Single query. Send this or keywords, never both.
namestringnoClicks: <first keyword>Campaign name as it appears in the dashboard.
targetstringyesURL/domain to find and click in the SERP.
quantityintegeryesClicks to deliver (1–1,000,000), across all keywords. Must be ≥ the number of keywords.
geoobjectno{ country? } — ISO-3166 alpha-2, country-level targeting.
deviceenumnomixeddesktop, mobile, mixed.
pacingenumnoasapasap delivers as fast as capacity allows; distributed spreads clicks naturally over spread_hours.
spread_hoursintegerno24For pacing: "distributed": spread the clicks over this many hours (1–720).
search_max_pagesinteger (1–10)no5How deep into the SERP to look for and deliver the target. A shallow 1–3-page miss is not enough evidence for the automatic not-ranking guard.
dwell_seconds_min / dwell_seconds_maxintegerno30 / 120Time on the clicked page.
pages_per_visitintegerno2Internal pages browsed after the click.
tagstringnoFree-form label.

* Exactly one of keywords or keyword is required.

An account may create up to 25 SEO traffic projects per UTC day by default. The counter is shared by dashboard projects and Traffic API campaigns. Deleting a project does not refund its creation slot; failed requests do not consume one. Operators can change the runtime limit, and 0 disables rejection.

If a page targets several queries, send them as keywords in a single request. You get one campaign to name, watch and poll instead of one per keyword — which matters at volume: 150 URLs × 6 keywords is 900 campaigns if you split them, and 150 if you don’t.

quantity is the total across the campaign and is split evenly, remainder first, so the parts always sum to what you bought. quantity: 200 over 3 keywords gives 67 / 67 / 66.

A head term and a long-tail term rarely deserve the same number of clicks, so you can set each share yourself:

{
"name": "Acme — running shoes cluster",
"quantity": 100,
"keywords": [
{ "keyword": "best running shoes", "quantity": 70 },
{ "keyword": "trail running shoes", "quantity": 20 },
{ "keyword": "cheap running shoes", "quantity": 10 }
]
}

Set quantity on every keyword or on none — mixing the two is rejected, because guessing a share for the unset ones would change what you bought for the ones you did specify. Explicit shares must sum exactly to the campaign quantity, so a campaign can never quietly under-deliver what you paid for.

HTTP 202 with a campaign whose product is clicks. A click is only counted (and billed) when the browser actually finds the target within search_max_pages and clicks through — if the target isn’t found on a given attempt, you are not charged for it.

GET /v1/traffic/campaigns/{id} returns a keywords array alongside the campaign totals:

{
"campaign_id": "9f1c…",
"name": "Acme — running shoes cluster",
"product": "clicks",
"quantity": 200,
"delivered": 118,
"status": "running",
"keywords": [
{ "keyword": "best running shoes", "quantity": 67, "delivered": 67, "status": "completed" },
{ "keyword": "trail running shoes", "quantity": 67, "delivered": 51, "status": "delivering" },
{ "keyword": "cheap running shoes", "quantity": 66, "delivered": 0, "status": "not_ranking" }
]
}
Keyword statusMeaning
deliveringWorking through its share of the quantity.
completedDelivered its full share.
not_rankingRepeated searches could not find your target within search_max_pages, so this keyword was switched off. It will never deliver — replace it, or raise search_max_pages. You were not charged for those searches.

not_ranking is the one to watch if you generate keywords programmatically: it is the difference between a campaign that is merely slow and one that can never finish. A campaign whose remaining keywords are all not_ranking will stop short of quantity, and the unspent balance stays on your account.

  • A genuine browser performs the search, so the click is a real organic SERP interaction (not a synthetic hit on your URL).
  • Natural dwell and post-click browsing produce realistic engagement signals.
  • geo/device route through matching residential/mobile proxies.

This is a measurement and testing tool. Serplify does not guarantee ranking changes, and you must be authorised to drive traffic to the target. See the Acceptable Use policy.