p202 report winners

Rows to SCALE: profitable, converting keywords/geos; closers come back as CLOSER

All commands

01Run it

Replace the <placeholders> with your own values, or use the builder below.

p202 report winners

02What you get

Captured from the real binary, run against a demo store with 30 days of traffic. Switch tabs to see the same run as JSON, the shape scripts and agents parse.

p202 report winners --breakdown keyword --period last30
$ p202 report winners --breakdown keyword --period last30
id  name                         Clicks  Conversions  Cost    Profit   Avg CPC  bucket  reason                    assisted_conversions  first_touch_roi
--  ---------------------------  ------  -----------  ------  -------  -------  ------  ------------------------  --------------------  ---------------
8   team task tracker            47      4            112.80  1519.20  2.40     SCALE   profit +$1519.20, 4 conv  0                     1346.81
1   standing desk uk             62      2            68.20   1114.80  1.10     SCALE   profit +$1114.80, 2 conv  0                     1634.60
3   spring outfits               134     7            57.66   834.34   0.4303   SCALE   profit +$834.34, 7 conv   0                     1447
10  wrap dress                   156     5            66.90   675.10   0.4288   SCALE   profit +$675.10, 5 conv   0                     1009.12
18  linen shirt men              80      4            52      640      0.65     SCALE   profit +$640.00, 4 conv   0                     1230.77
2   gift cards australia         54      4            25.92   599.08   0.48     SCALE   profit +$599.08, 4 conv   0                     2311.27
5   height adjustable desk       64      2            70.40   595.60   1.10     SCALE   profit +$595.60, 2 conv   0                     846.02
11  gantt chart tool             49      1            117.60  470.40   2.40     SCALE   profit +$470.40, 1 conv   0                     400
15  linen shirt                  148     3            63.54   308.46   0.4293   SCALE   profit +$308.46, 3 conv   0                     485.46
13  project management software  54      1            129.60  218.40   2.40     SCALE   profit +$218.40, 1 conv   0                     168.52
9   fresh roasted coffee         65      5            24.70   187.30   0.38     SCALE   profit +$187.30, 5 conv   0                     758.30
12  whole bean coffee delivery   70      5            26.60   185.40   0.38     SCALE   profit +$185.40, 5 conv   0                     696.99
7   wrap dress midi              86      2            55.90   176.10   0.65     SCALE   profit +$176.10, 2 conv   0                     315.03
20  digital gift card            54      2            25.92   149.08   0.48     SCALE   profit +$149.08, 2 conv   0                     575.15
16  coffee subscription          75      4            28.50   125.50   0.38     SCALE   profit +$125.50, 4 conv   0                     440.35
4   last minute gift             52      2            24.96   100.04   0.48     SCALE   profit +$100.04, 2 conv   0                     400.80
19  free project planner         51      4            91.80   24.20    1.80     SCALE   profit +$24.20, 4 conv    0                     26.36
Real output · p202 1.9.78 · demo dataexit 0

Profit by keyword

  • team task tracker$1,519.20
  • standing desk uk$1,114.80
  • spring outfits$834.34
  • wrap dress$675.10
  • linen shirt men$640.00
  • gift cards australia$599.08
  • height adjustable desk$595.60
  • gantt chart tool$470.40
  • linen shirt$308.46
  • project management software$218.40
  • fresh roasted coffee$187.30
  • whole bean coffee delivery$185.40

Drawn from the JSON output above.

03Build your command

Pick values and the command line writes itself, quoted and ready to paste.

p202 report winners

Set flags below; the command updates as you type.

04Flags

26 flags, plus the global flags every command takes.

FlagWhat it does
--aff-campaign-idstringFilter by INTERNAL campaign id (from campaign list), not the public id in tracking URLs
--aff-network-idstringFilter by affiliate network ID
--breakdown, -bstring · default keywordDimension to triage: campaign, aff_network, ppc_account, ppc_network, landing_page, keyword, country, city, region, browser, platform, device, isp, text_ad, ip, referer, referer_url, device_type, c1, c2, c3, c4, utm_source, utm_medium, utm_campaign, utm_term, utm_content, rotator, rotator_rule (aliases: geo=country, lp=landing_page, network=aff_network, offer=campaign, referrer=referer, referrer_url=referer_url, rule=rotator_rule, source=ppc_account)
campaignaff_networkppc_accountppc_networklanding_pagekeywordcountrycityregionbrowserplatformdeviceisptext_adiprefererreferer_urldevice_typec1c2c3c4utm_sourceutm_mediumutm_campaignutm_termutm_contentrotatorrotator_rulegeo → countrylp → landing_pagenetwork → aff_networkoffer → campaignreferrer → refererreferrer_url → referer_urlrule → rotator_rulesource → ppc_account
--browser-idstringFilter by browser ID (the id of a --breakdown browser row)
--country-idstringFilter by country ID
--device-typestringFilter by device type ID: 1 Desktop, 2 Mobile, 3 Tablet, 4 Bot (the ids of --breakdown device_type rows)
--first-touch-modelstringAttribution model id for the closer check (default: the first active First touch model)
--ipstringOnly clicks from this one IP address, IPv4 or IPv6
--isp-idstringFilter by ISP/carrier ID (the id of a --breakdown isp row)
--keywordstringOnly clicks whose keyword contains this text (case-insensitive)
--landing-page-idstringFilter by landing page ID
--max-cpcfloat64Break-even CPC target (else payout × each row's CVR, from --payout or the campaign)
--method-of-promotionstringOnly direct-link clicks or only landing-page clicks: directlink, landingpage
directlinklandingpage
--min-clicksfloat64 · default 1Ignore rows with fewer than N clicks (significance floor)
--no-attribution-checkboolList classic last-click winners only, without the first-touch closer check
--payoutfloat64Revenue per conversion, e.g. your average order value: each row's break-even CPC is this × its conversion rate, and its profit (total_net) and first-touch ROI value each sale at this. Unlike --aff-campaign-id it doesn't filter the report, so the attribution check still runs
--period, -pstringPeriod: today, yesterday, last7, last14, last30, last90, thismonth, lastmonth, thisyear, lastyear, alltime
todayyesterdaylast7last14last30last90thismonthlastmonththisyearlastyearalltime
--platform-idstringFilter by platform (OS) ID (the id of a --breakdown platform row)
--ppc-account-idstringFilter by PPC account ID
--ppc-network-idstringFilter by PPC network ID, or none for the clicks with no traffic source
--refererstringOnly clicks whose referring URL contains this text (case-insensitive)
--region-idstringFilter by region ID (the id of a --breakdown region row)
--showstringWhich clicks count (default all): all, real, filtered, filtered_bot, leads; real = not filtered, filtered_bot = filtered as bots, leads = converted
allrealfilteredfiltered_botleads
--text-ad-idstringFilter by text ad ID
--time-fromstringStart: unix seconds, a date (2026-10-01, from its first second in the account's timezone) or a time with its offset (2026-10-01T09:30:00Z)
--time-tostringEnd, inclusive: unix seconds, a date (2026-10-01, through its last second in the account's timezone) or a time with its offset

05How it works

Rows to SCALE from the classic (last-click) report: profitable and converting. Profit is the campaign's recorded income less cost, or with --payout (your revenue per conversion) sales × payout less cost, the value the first-touch ROI below then uses too. Sales are counted with the Last touch model where the check can read it (a converted click can have several), so a source profitable only through repeat sales is listed too.

Each SCALE row is then checked against the attribution report under a first-touch model, for the same dimension and range. A row that loses money under first touch comes back as CLOSER, with its first-touch ROI and assists: last-click credits it with sales other rows started (retargeting, brand search and email often look like this), so more budget won't bring more new buyers. Check what feeds it before scaling.

The check runs for campaign, ppc_account (traffic source), landing_page, keyword and country, and needs a First touch model (the first active one, or --first-touch-model) and an attribution:read key. When it can't run, the classic winners are still listed with the reason on stderr. A filter other than the breakdown itself (an entity id, --keyword, --show, ...) turns it off; --no-attribution-check does too.

06For agents

Running this from an agent

  • Read the same facts as JSON: p202 commands report winners --json.
  • With AI_AGENT, CLAUDECODE or another agent variable set, output is compact JSON and errors arrive on stderr as a JSON envelope with a hint.
  • Exit codes: 0 ok, 1 bad input, 2 auth, 3 network, 4 server error, 5 partial failure, 6 no Pro licence on the install.
p202 commands report winners --json
{
  "path": "p202 report winners",
  "use": "winners",
  "short": "Rows to SCALE: profitable, converting keywords/geos; closers come back as CLOSER",
  "long": "Rows to SCALE from the classic (last-click) report: profitable and converting. Profit is the campaign's\nrecorded income less cost, or with --payout (your revenue per conversion) sales × payout less cost, the value the\nfirst-touch ROI below then uses too. Sales are counted with the Last touch model where the check can read it\n(a converted click can have several), so a source profitable only through repeat sales is listed too.\n\nEach SCALE row is then checked against the attribution report under a first-touch model, for the same dimension\nand range. A row that loses money under first touch comes back as CLOSER, with its first-touch ROI and assists:\nlast-click credits it with sales other rows started (retargeting, brand search and email often look like this),\nso more budget won't bring more new buyers. Check what feeds it before scaling.\n\nThe check runs for campaign, ppc_account (traffic source), landing_page, keyword and country, and needs a First\ntouch model (the first active one, or --first-touch-model) and an attribution:read key. When it can't run, the\nclassic winners are still listed with the reason on stderr. A filter other than the breakdown itself (an entity\nid, --keyword, --show, ...) turns it off; --no-attribution-check does too.",
  "runnable": true,
  "flags": [
    {
      "name": "aff-campaign-id",
      "type": "string",
      "default": "",
      "usage": "Filter by INTERNAL campaign id (from `campaign list`), not the public id in tracking URLs",
      "required": false
    },
    {
      "name": "aff-network-id",
      "type": "string",
      "default": "",
      "usage": "Filter by affiliate network ID",
      "required": false
    },
    {
      "name": "breakdown",
      "shorthand": "b",
      "type": "string",
      "default": "keyword",
      "usage": "Dimension to triage: campaign, aff_network, ppc_account, ppc_network, landing_page, keyword, country, city, region, browser, platform, device, isp, text_ad, ip, referer, referer_url, device_type, c1, c2, c3, c4, utm_source, utm_medium, utm_campaign, utm_term, utm_content, rotator, rotator_rule (aliases: geo=country, lp=landing_page, network=aff_network, offer=campaign, referrer=referer, referrer_url=referer_url, rule=rotator_rule, source=ppc_account)",
      "allowed_values": [
        "campaign",
        "aff_network",
        "ppc_account",
        "ppc_network",
        "landing_page",
        "keyword",
        "country",
        "city",
        "region",
        "browser",
        "platform",
        "device",
        "isp",
        "text_ad",
        "ip",
        "referer",
        "referer_url",
        "device_type",
        "c1",
        "c2",
        "c3",
        "c4",
        "utm_source",
        "utm_medium",
        "utm_campaign",
        "utm_term",
        "utm_content",
        "rotator",
        "rotator_rule"
      ],
      "value_aliases": {
        "geo": "country",
        "lp": "landing_page",
        "network": "aff_network",
        "offer": "campaign",
        "referrer": "referer",
        "referrer_url": "referer_url",
        "rule": "rotator_rule",
        "source": "ppc_account"
      },
      "required": false
    },
    {
      "name": "browser-id",
      "type": "string",
      "default": "",
      "usage": "Filter by browser ID (the id of a `--breakdown browser` row)",
      "required": false
    },
    {
      "name": "country-id",
      "type": "string",
      "default": "",
      "usage": "Filter by country ID",
      "required": false
    },
    {
      "name": "device-type",
      "type": "string",
      "default": "",
      "usage": "Filter by device type ID: 1 Desktop, 2 Mobile, 3 Tablet, 4 Bot (the ids of `--breakdown device_type` rows)",
      "required": false
    },
    {
      "name": "first-touch-model",
      "type": "string",
      "default": "",
      "usage": "Attribution model id for the closer check (default: the first active First touch model)",
      "required": false
    },
    {
      "name": "ip",
      "type": "string",
      "default": "",
      "usage": "Only clicks from this one IP address, IPv4 or IPv6",
      "required": false
    },
    {
      "name": "isp-id",
      "type": "string",
      "default": "",
      "usage": "Filter by ISP/carrier ID (the id of a `--breakdown isp` row)",
      "required": false
    },
    {
      "name": "keyword",
      "type": "string",
      "default": "",
      "usage": "Only clicks whose keyword contains this text (case-insensitive)",
      "required": false
    },
    {
      "name": "landing-page-id",
      "type": "string",
      "default": "",
      "usage": "Filter by landing page ID",
      "required": false
    },
    {
      "name": "max-cpc",
      "type": "float64",
      "default": "0",
      "usage": "Break-even CPC target (else payout × each row's CVR, from --payout or the campaign)",
      "required": false
    },
    {
      "name": "method-of-promotion",
      "type": "string",
      "default": "",
      "usage": "Only direct-link clicks or only landing-page clicks: directlink, landingpage",
      "allowed_values": [
        "directlink",
        "landingpage"
      ],
      "required": false
    },
    {
      "name": "min-clicks",
      "type": "float64",
      "default": "1",
      "usage": "Ignore rows with fewer than N clicks (significance floor)",
      "required": false
    },
    {
      "name": "no-attribution-check",
      "type": "bool",
      "default": "false",
      "usage": "List classic last-click winners only, without the first-touch closer check",
      "required": false
    },
    {
      "name": "payout",
      "type": "float64",
      "default": "0",
      "usage": "Revenue per conversion, e.g. your average order value: each row's break-even CPC is this × its conversion rate, and its profit (total_net) and first-touch ROI value each sale at this. Unlike --aff-campaign-id it doesn't filter the report, so the attribution check still runs",
      "required": false
    },
    {
      "name": "period",
      "shorthand": "p",
      "type": "string",
      "default": "",
      "usage": "Period: today, yesterday, last7, last14, last30, last90, thismonth, lastmonth, thisyear, lastyear, alltime",
      "allowed_values": [
        "today",
        "yesterday",
        "last7",
        "last14",
        "last30",
        "last90",
        "thismonth",
        "lastmonth",
        "thisyear",
        "lastyear",
        "alltime"
      ],
      "required": false
    },
    {
      "name": "platform-id",
      "type": "string",
      "default": "",
      "usage": "Filter by platform (OS) ID (the id of a `--breakdown platform` row)",
      "required": false
    },
    {
      "name": "ppc-account-id",
      "type": "string",
      "default": "",
      "usage": "Filter by PPC account ID",
      "required": false
    },
    {
      "name": "ppc-network-id",
      "type": "string",
      "default": "",
      "usage": "Filter by PPC network ID, or none for the clicks with no traffic source",
      "required": false
    },
    {
      "name": "referer",
      "type": "string",
      "default": "",
      "usage": "Only clicks whose referring URL contains this text (case-insensitive)",
      "required": false
    },
    {
      "name": "region-id",
      "type": "string",
      "default": "",
      "usage": "Filter by region ID (the id of a `--breakdown region` row)",
      "required": false
    },
    {
      "name": "show",
      "type": "string",
      "default": "",
      "usage": "Which clicks count (default all): all, real, filtered, filtered_bot, leads; real = not filtered, filtered_bot = filtered as bots, leads = converted",
      "allowed_values": [
        "all",
        "real",
        "filtered",
        "filtered_bot",
        "leads"
      ],
      "required": false
    },
    {
      "name": "text-ad-id",
      "type": "string",
      "default": "",
      "usage": "Filter by text ad ID",
      "required": false
    },
    {
      "name": "time-from",
      "type": "string",
      "default": "",
      "usage": "Start: unix seconds, a date (2026-10-01, from its first second in the account's timezone) or a time with its offset (2026-10-01T09:30:00Z)",
      "required": false
    },
    {
      "name": "time-to",
      "type": "string",
      "default": "",
      "usage": "End, inclusive: unix seconds, a date (2026-10-01, through its last second in the account's timezone) or a time with its offset",
      "required": false
    }
  ]
}