@buygolinks/mcp 0.27.0 → 0.28.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +2 -2
- package/src/index.js +4 -3
package/README.md
CHANGED
|
@@ -72,7 +72,7 @@ Most MCP clients use the same shape. Point them at the `npx -y @buygolinks/mcp`
|
|
|
72
72
|
| `create_domain` | Register a new branded domain (e.g. `go.acme.com`). Returns the CNAME target. |
|
|
73
73
|
| `verify_domain` | Force a fresh Cloudflare status check after DNS is added. |
|
|
74
74
|
| `delete_domain` | Remove a branded domain. |
|
|
75
|
-
| `get_universal_postback_url` | Get the account's **universal postback URL** (Voluum-style, `/postback/u/{token}`): ONE URL that works for every campaign and every network. It matches the click by `clickid` (alias `cid`) and credits whichever campaign the click belongs to — paste it once into any network's S2S settings or your own webhook (n8n, Zapier, store order webhooks) and never update it again. Optional `payout`, `currency`, `txid` params. Prefer this over per-campaign/per-network postbacks unless you want campaign-scoped validation. |
|
|
75
|
+
| `get_universal_postback_url` | Get the account's **universal postback URL** (Voluum-style, `/postback/u/{token}`): ONE URL that works for every campaign and every network. It matches the click by `clickid` (alias `cid`) and credits whichever campaign the click belongs to — paste it once into any network's S2S settings or your own webhook (n8n, Zapier, store order webhooks) and never update it again. Optional `payout`, `currency`, `txid` params. Prefer this over per-campaign/per-network postbacks unless you want campaign-scoped validation. Conversions are deduped by txid: at most one conversion per (account, txid) — a re-fired postback with the same txid is ignored, and a re-fire with a different payout updates the stored conversion's revenue instead of stacking a second one. |
|
|
76
76
|
| `list_affiliate_networks` / `create_affiliate_network` / `update_affiliate_network` / `delete_affiliate_network` | Manage affiliate networks. Each network exposes a per-network postback URL (`/postback/n/{token}`) the user pastes into the network's S2S settings. Set `amazon_tag` (e.g. `yourtagid-20`) on an Amazon network to auto-tag every Amazon link with `?tag=…` at click time. |
|
|
77
77
|
| `list_offers` / `create_offer` / `update_offer` / `delete_offer` | Manage destination URLs ("offers"). Optionally tied to an affiliate network so the right conversion-param name is propagated on outbound clicks. |
|
|
78
78
|
| `list_landers` / `create_lander` / `update_lander` / `delete_lander` | Manage landing pages. Lander URLs may contain `{clickid}` tokens which the resolver expands. |
|
|
@@ -81,7 +81,7 @@ Most MCP clients use the same shape. Point them at the `npx -y @buygolinks/mcp`
|
|
|
81
81
|
| `list_campaigns` / `create_campaign` / `get_campaign` / `update_campaign` / `delete_campaign` / `duplicate_campaign` | Manage campaigns. `duplicate_campaign` deep-copies a campaign (settings + full routing flow + offer/lander pools) into a fresh short link named `COPY - {name}` (`COPY (1) - …` when copying a copy); stats and the unique direct-link tags are not carried over. One campaign = one tracked short link + N offers (weighted) + N optional landers + a per-campaign postback URL + a pixel snippet. A campaign references one saved traffic source via `traffic_source_id` and an optional `conversion_pixel_id` + `conversion_event` that fires **server-side via the pixel's CAPI token** when the campaign converts (a pixel with no CAPI token can't fire back). `report_value_mode` controls the value reported back — `payout` (real), `fixed` (a set number), or `adjusted` (payout − `report_value_adjust_pct`% − `report_value_adjust_flat`) so you can withhold your margin. Each campaign also returns a `click_url` (`…/click`) — the single, campaign-agnostic lander CTA link (same on every campaign, so one lander serves many) that always resolves to an offer (never a dead page); the campaign is read from the visitor's cookie or the ad's `?utm_campaign={slug}` (matched against any of the campaign's direct-link tags) forwarded onto the CTA. As of **0.22.0**, `create_campaign`/`update_campaign` gained **`direct_slugs`** — a campaign can claim MULTIPLE direct-link tags (an array of strings or `{ slug, label }` objects, each routing through the campaign's flow) so you run traffic straight to a lander with no tracker hop (`?utm_campaign={slug}` resolves the campaign at `/click` and stitches via the property tag); handy for migrating an older campaign or turning a lander already getting direct traffic into a campaign. The legacy single `direct_slug` is deprecated but still accepted (responses mirror it to the oldest slug). `fallback_url` is the never-dead-end guarantee. |
|
|
82
82
|
| `set_campaign_offers` / `set_campaign_landers` | Replace the campaign's offer/lander split. Items are `{ offer_id, weight }` / `{ lander_id, weight }`. |
|
|
83
83
|
| `get_campaign_flow` / `set_campaign_flow` | Read/replace the campaign's **routing flow graph** (n8n-style). Nodes are `source` (one entry) / `lander` / `offer`; weighted edges go source→lander, source→offer, or lander→offer. The resolver walks this graph per click so a specific lander routes to its own specific offers — use it to split-test offers, divert a lander to a different offer, or insert a landing page before an offer. Saving also re-derives the flat offer/lander pools. |
|
|
84
|
-
| `get_campaign_stats` | Full campaign report: visits, lander views, offer clicks, conversions, revenue, cost, profit, CTR/CR/EPC/ROI, recent events, plus Voluum-style `breakdowns` — grouped rows (`{key, visits, clicks, conversions, revenue, ctr, cr, epc}`) for
|
|
84
|
+
| `get_campaign_stats` | Full campaign report: visits, lander views, offer clicks, conversions, revenue, cost, profit, CTR/CR/EPC/ROI, recent events, plus Voluum-style `breakdowns` — grouped rows (`{key, visits, clicks, conversions, revenue, ctr, cr, epc}`) for 9 dimensions: utm_campaign / utm_source / utm_content / utm_term / lander / offer / country / device / day. Downstream events attribute to the utm values of the visit that minted their click_id; the `offer` dimension attributes each visit to the offer its click routed to (keyed by offer name); the `lander` dimension is the page the click came from (host+path — full paths for pages running the property tag, ad-platform hosts for straight-from-ad clicks); empty values group as `(none)`. **Drill-down:** pass any dimension as a filter (e.g. `utm_campaign` + read `breakdowns.offer` to see which split-test offer converts for that ad) — the whole report narrows to that slice; filters combine. Window: rolling `days` or an explicit `from`/`to` range. |
|
|
85
85
|
| `list_properties` / `create_property` / `get_property` / `update_property` / `delete_property` | Manage **properties** — GTM/GA-style site containers. One property = one universal tag (`/t.js?p={key}`) the user installs on every page of their site. Every page auto-reports pageviews, time-on-page, scroll, outbound clicks, and conversions; campaign traffic auto-attributes by click. `create_property` requires an active custom domain (the tag is served first-party from the user's own domain so it tracks on iOS/Safari) and returns the bound `tracking_domain` + install `snippet`. |
|
|
86
86
|
| `set_property_campaigns` | Link/unlink campaigns to a property (many-to-many, for the source split in reports). Items are `{ campaign_id }`. |
|
|
87
87
|
| `get_property_stats` | Full property report: page views, unique visitors, outbound, conversions, revenue, avg time/scroll, top pages, source split (organic vs campaign), country/device/browser/referrer breakdowns, recent events. |
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buygolinks/mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "MCP server for buygolinks.com
|
|
3
|
+
"version": "0.28.1",
|
|
4
|
+
"description": "MCP server for buygolinks.com \u2014 create and manage branded short links with Amazon affiliate geo-routing from any MCP-compatible AI agent (Claude Desktop, Cursor, Cline, Continue, Hermes).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"buygolinks-mcp": "src/index.js"
|
package/src/index.js
CHANGED
|
@@ -200,7 +200,7 @@ const TOOLS = [
|
|
|
200
200
|
{
|
|
201
201
|
name: 'get_universal_postback_url',
|
|
202
202
|
description:
|
|
203
|
-
'Get the account\'s UNIVERSAL postback URL (Voluum-style): ONE URL that works for every campaign and every affiliate network. It matches the click by click_id alone and credits whichever campaign the click belongs to, so the user pastes it once into any network\'s S2S settings or their own webhook (n8n, Zapier, a store\'s order webhook) and never updates it again. Format: https://buygolinks.com/postback/u/{token}?clickid={clickid}&payout={payout}¤cy={currency}&txid={txid} — payout/currency/txid optional; `cid` is accepted as an alias for `clickid`. Prefer this over per-campaign or per-network postback URLs unless the user explicitly wants campaign-scoped validation (the per-campaign URL rejects clicks from other campaigns with a 400).',
|
|
203
|
+
'Get the account\'s UNIVERSAL postback URL (Voluum-style): ONE URL that works for every campaign and every affiliate network. It matches the click by click_id alone and credits whichever campaign the click belongs to, so the user pastes it once into any network\'s S2S settings or their own webhook (n8n, Zapier, a store\'s order webhook) and never updates it again. Format: https://buygolinks.com/postback/u/{token}?clickid={clickid}&payout={payout}¤cy={currency}&txid={txid} — payout/currency/txid optional; `cid` is accepted as an alias for `clickid`. Prefer this over per-campaign or per-network postback URLs unless the user explicitly wants campaign-scoped validation (the per-campaign URL rejects clicks from other campaigns with a 400). Conversions are deduped by txid: at most one conversion per (account, txid) — a re-fired postback with the same txid is ignored, and a re-fire with a different payout updates the stored conversion\'s revenue instead of stacking a second one.',
|
|
204
204
|
inputSchema: { type: 'object', properties: {} },
|
|
205
205
|
},
|
|
206
206
|
{
|
|
@@ -615,7 +615,7 @@ const TOOLS = [
|
|
|
615
615
|
{
|
|
616
616
|
name: 'get_campaign_stats',
|
|
617
617
|
description:
|
|
618
|
-
'Get a campaign\'s full report: totals (visits / unique / lander_views / offer_clicks / conversions / revenue / cost / profit / CTR / CR / EPC / ROI), by_day / by_country / by_device / by_browser / by_referrer / by_hour, per-offer and per-lander performance, the 50 most recent events, and `breakdowns` — Voluum-style grouped report rows for
|
|
618
|
+
'Get a campaign\'s full report: totals (visits / unique / lander_views / offer_clicks / conversions / revenue / cost / profit / CTR / CR / EPC / ROI), by_day / by_country / by_device / by_browser / by_referrer / by_hour, per-offer and per-lander performance, the 50 most recent events, and `breakdowns` — Voluum-style grouped report rows for 9 dimensions (utm_campaign / utm_source / utm_content / utm_term / lander / offer / country / device / day), each row {key, visits, clicks, conversions, revenue, ctr, cr, epc}. Offer clicks and conversions are attributed to the utm values of the visit that minted their click_id (postback conversions landing after the visit included); the `offer` dimension attributes each visit to the offer its click routed to (keyed by offer NAME), so split-test rows read correctly; the `lander` dimension is the page the click came FROM (visit referrer normalized to host+path — full paths for landers running the property tag, ad-platform hosts like m.facebook.com for straight-from-ad clicks); traffic with no value groups under "(none)". DRILL-DOWN: pass any dimension as a filter (e.g. utm_campaign="Summer Sale", lander="promo.example.com/lander-a", or offer="My Offer") and the WHOLE report — totals, by_day, breakdowns — narrows to that traffic slice; combine filters to drill deeper (e.g. utm_campaign + group the result\'s `breakdowns.offer` to see which offer converts for that ad). Pass "(none)" to match events with no value.',
|
|
619
619
|
inputSchema: {
|
|
620
620
|
type: 'object',
|
|
621
621
|
properties: {
|
|
@@ -627,6 +627,7 @@ const TOOLS = [
|
|
|
627
627
|
utm_source: { type: 'string', description: 'Drill-down filter by utm_source.' },
|
|
628
628
|
utm_content: { type: 'string', description: 'Drill-down filter by utm_content.' },
|
|
629
629
|
utm_term: { type: 'string', description: 'Drill-down filter by utm_term.' },
|
|
630
|
+
lander: { type: 'string', description: 'Drill-down filter by lander page (host+path, as returned in breakdowns.lander keys).' },
|
|
630
631
|
offer: { type: 'string', description: 'Drill-down filter by offer NAME (as returned in breakdowns.offer keys).' },
|
|
631
632
|
country: { type: 'string', description: 'Drill-down filter by ISO2 country of the minting visit.' },
|
|
632
633
|
device: { type: 'string', description: 'Drill-down filter by device of the minting visit.' },
|
|
@@ -1088,7 +1089,7 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
1088
1089
|
if (args?.from) qs.set('from', String(args.from));
|
|
1089
1090
|
if (args?.to) qs.set('to', String(args.to));
|
|
1090
1091
|
if (args?.days && !args?.from) qs.set('days', String(Number(args.days)));
|
|
1091
|
-
for (const dim of ['utm_campaign', 'utm_source', 'utm_content', 'utm_term', 'offer', 'country', 'device', 'day']) {
|
|
1092
|
+
for (const dim of ['utm_campaign', 'utm_source', 'utm_content', 'utm_term', 'lander', 'offer', 'country', 'device', 'day']) {
|
|
1092
1093
|
if (args?.[dim]) qs.set(dim, String(args[dim]));
|
|
1093
1094
|
}
|
|
1094
1095
|
const q = qs.toString();
|