API reference
Campaign links
The API operations about campaign links, each with its input, its output and an example.
The operations about campaign links. Each one is a POST with a JSON object as its body: Making a request has the rules they share.
Campaign breakdown #
POST /api/v1/campaigns.breakdown · Read
Campaign traffic of one site in a period, one row per campaign (utm_campaign), source (utm_source), medium (utm_medium) or pair of source and medium, with visitors, page views, conversions, credited orders and credited revenue. Get the siteId from sites.list first. Only campaign visits are counted: visits that arrived with at least one campaign tag (utm_source, utm_medium, utm_campaign, utm_term or utm_content). A conversion is a completion of an enabled conversion goal, or any custom event when the site has no enabled goal. The conversion filter is ignored by the campaign reports; every other filter applies. It pages by offset: limit rows (10 unless set, 100 at most) starting at offset. The number of rows there are is in total (not totalRows), and at most 1000 rows are listed. Rows are ordered by visitors, then page views, then label; search keeps the rows whose label, key or saved name contains the text. On the campaign dimension the saved campaign links (campaigns.list) are listed too, with zeros when they had no traffic, and created names the saved link of a row. Tags are grouped ignoring case. The row with an empty key is the campaign visits that lack the tag. revenueMinor is in minor units of currency. The comparison is not used. Answers 402 workspace_locked while the workspace's dashboards are locked.
Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.
Input #
| Field | Type | Required | Description |
|---|---|---|---|
siteId |
string | required | The site id, from sites.list. |
range |
"today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" | optional | The period to report on: one of today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace's default range is used (30d unless it was changed). For exact dates send from and to and leave range out (custom is accepted with them and means the same). A preset together with dates answers 400. |
from |
string | optional | First day of a custom period, YYYY-MM-DD in the site's time zone. Send it together with to: one without the other answers 400, and so does a day that does not exist or a from after to. A day after today is read as today; window in the answer shows the period that was used. |
to |
string | optional | Last day of a custom period, inclusive, YYYY-MM-DD in the site's time zone. Send it together with from. |
compare |
"prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" | optional | What the period is compared with: prev (the period just before, the default), week, month, quarter or year earlier, custom (cfrom and cto are then required), or off for no comparison. The range all never has a comparison. |
cfrom |
string | optional | First day of a custom comparison period, YYYY-MM-DD. Required with compare set to custom, where a day that does not exist or a cfrom after cto answers 400. |
cto |
string | optional | Last day of a custom comparison period, inclusive, YYYY-MM-DD. Required with compare set to custom. |
filters |
object | optional | Narrow the numbers to matching traffic. An object such as { "country": "us", "path.has": "pricing" }. A plain key means "is"; a key ending in .not means "is not" and a key ending in .has means "contains". Filters are joined with AND. At most 10 keys, of which at most 3 may end in .has. Default: {}. The filter keys are listed under Filters. |
dimension |
"campaign" | "source" | "medium" | "source_medium" | required | What to group by: campaign (utm_campaign), source (utm_source), medium (utm_medium) or source_medium (the pair). |
limit |
integer, 1 to 100 | optional | Rows per page, 1 to 100. 10 when left out. |
offset |
integer, 0 to 1000 | optional | Rows to skip, 0 to 1000. offset plus limit may not be more than 1000. |
search |
string, 1 to 100 characters | optional | Keep only rows whose label, key or saved campaign name contains this text, ignoring case. 1 to 100 characters. |
Output #
| Field | Type | Present | Description |
|---|---|---|---|
serverNow |
number | always | The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC. |
serverTime |
number | always | When the answer was built, milliseconds since 1970 UTC. |
window |
object | always | The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size. |
compare |
object | null | always | The comparison period in the same form, or null when there is none. |
rawFrom |
number | null | always | The earliest time detailed data is kept from, or null when nothing was trimmed. |
truncated |
boolean | always | True when a filtered answer could only cover the part of the period that still has detailed data. |
rows |
array of object | always | One row per campaign, source, medium, or source and medium pair, most visitors first. key is the tag in lower case, which is what a utm filter takes, and label is the tag as it was first seen. The row with an empty key and the label (not set) is the campaign visits without that tag. visitors, views, conversions and orders are counts for the row; revenueMinor is the revenue credited to it in minor units (cents) of currency, or null. On the campaign dimension, created is the saved campaign link with that key ({ id, name }) or null, and saved links without traffic are listed with zeros, last. |
total |
number | always | The number of rows after the search. Page with limit and offset until offset reaches it. At most 1,000 rows are listed, so it stops there too. |
currency |
string | null | always | The currency of revenueMinor, an ISO 4217 code, or null when the site never had an order. |
Example #
curl -s -X POST https://clearsaga.com/api/v1/campaigns.breakdown \
-H "Authorization: Bearer $CLEARSAGA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"siteId":"site_abc123def456","dimension":"campaign"}'clearsaga campaigns breakdown --input '{"siteId":"site_abc123def456","dimension":"campaign"}'Tool: campaigns_breakdown
Arguments: {"siteId":"site_abc123def456","dimension":"campaign"}Run clearsaga help campaigns breakdown for one flag per field.
Campaign conversions #
POST /api/v1/campaigns.conversions · Read
Which conversions each campaign led to on one site in a period: one row per campaign and conversion name with how often it happened, most frequent first. Get the siteId from sites.list first. Only campaign visits are counted: visits that arrived with at least one campaign tag (utm_source, utm_medium, utm_campaign, utm_term or utm_content). A conversion is a completion of an enabled conversion goal, or any custom event when the site has no enabled goal. The conversion filter is ignored by the campaign reports; every other filter applies. A hit that completes two goals is one row for each goal, so the rows can add up to more than the conversions of campaigns.totals. It pages by offset: limit rows (10 unless set, 100 at most) starting at offset. The number of rows there are is in total (not totalRows), and at most 1000 rows are listed. search matches the campaign or the conversion name. The comparison is not used. Answers 402 workspace_locked while the workspace's dashboards are locked.
Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.
Input #
| Field | Type | Required | Description |
|---|---|---|---|
siteId |
string | required | The site id, from sites.list. |
range |
"today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" | optional | The period to report on: one of today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace's default range is used (30d unless it was changed). For exact dates send from and to and leave range out (custom is accepted with them and means the same). A preset together with dates answers 400. |
from |
string | optional | First day of a custom period, YYYY-MM-DD in the site's time zone. Send it together with to: one without the other answers 400, and so does a day that does not exist or a from after to. A day after today is read as today; window in the answer shows the period that was used. |
to |
string | optional | Last day of a custom period, inclusive, YYYY-MM-DD in the site's time zone. Send it together with from. |
compare |
"prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" | optional | What the period is compared with: prev (the period just before, the default), week, month, quarter or year earlier, custom (cfrom and cto are then required), or off for no comparison. The range all never has a comparison. |
cfrom |
string | optional | First day of a custom comparison period, YYYY-MM-DD. Required with compare set to custom, where a day that does not exist or a cfrom after cto answers 400. |
cto |
string | optional | Last day of a custom comparison period, inclusive, YYYY-MM-DD. Required with compare set to custom. |
filters |
object | optional | Narrow the numbers to matching traffic. An object such as { "country": "us", "path.has": "pricing" }. A plain key means "is"; a key ending in .not means "is not" and a key ending in .has means "contains". Filters are joined with AND. At most 10 keys, of which at most 3 may end in .has. Default: {}. The filter keys are listed under Filters. |
limit |
integer, 1 to 100 | optional | Rows per page, 1 to 100. 10 when left out. |
offset |
integer, 0 to 1000 | optional | Rows to skip, 0 to 1000. offset plus limit may not be more than 1000. |
search |
string, 1 to 100 characters | optional | Keep only rows whose campaign or conversion name contains this text, ignoring case. 1 to 100 characters. |
Output #
| Field | Type | Present | Description |
|---|---|---|---|
serverNow |
number | always | The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC. |
serverTime |
number | always | When the answer was built, milliseconds since 1970 UTC. |
window |
object | always | The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size. |
compare |
object | null | always | The comparison period in the same form, or null when there is none. |
rawFrom |
number | null | always | The earliest time detailed data is kept from, or null when nothing was trimmed. |
truncated |
boolean | always | True when a filtered answer could only cover the part of the period that still has detailed data. |
rows |
array of object | always | One row per campaign and conversion, most frequent first: campaign is the campaign name, event the name of the conversion goal (or of the custom event when the site has no enabled goal), and count how often it happened in visits of that campaign. |
total |
number | always | The number of rows after the search. Page with limit and offset until offset reaches it. At most 1,000 rows are listed, so it stops there too. |
Example #
curl -s -X POST https://clearsaga.com/api/v1/campaigns.conversions \
-H "Authorization: Bearer $CLEARSAGA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"siteId":"site_abc123def456"}'clearsaga campaigns conversions --input '{"siteId":"site_abc123def456"}'Tool: campaigns_conversions
Arguments: {"siteId":"site_abc123def456"}Run clearsaga help campaigns conversions for one flag per field.
Create campaign link #
POST /api/v1/campaigns.create · Write
Saves a campaign link for one site: a destination address and the campaign tags to add to it. It appears on the Campaigns page of the dashboard at once, where members of the workspace copy and click the finished link, so only save an address they can trust. Traffic that arrives with the same utm_campaign value is matched to the saved link by its key, ignoring case. baseUrl must be an http or https address (400 invalid otherwise). utmMedium, utmTerm and utmContent must each be sent, as text or as null. The key must be unique among the saved links of the site (409 taken), and a site holds at most 200 (409 limit_reached). The medium is stored lower case, so read the saved values in the answer. Needs a token with the Write permission.
Input #
| Field | Type | Required | Description |
|---|---|---|---|
siteId |
string | required | The site id, from sites.list. |
key |
string | required | The utm_campaign value of the link: 1 to 120 characters from lower case letters, digits, dot, underscore, tilde and hyphen. Unique among the saved links of the site. Traffic is matched to the link by it. |
name |
string, 1 to 80 characters | required | The name the campaign is listed under in the dashboard, 1 to 80 characters. |
baseUrl |
string, at most 2000 characters | required | The address the link leads to, without campaign tags. A full http or https address of at most 2,000 characters, such as the address of your pricing page. |
utmSource |
string | required | The utm_source value: where the link is placed, for example newsletter. 1 to 120 characters from lower case letters, digits, dot, underscore, tilde, hyphen and space. |
utmMedium |
string, at most 120 characters | null | required | The utm_medium value, for example email, at most 120 characters, or null for none. The key must be sent. It is stored lower case. |
utmTerm |
string, at most 120 characters | null | required | The utm_term value, at most 120 characters, or null for none. The key must be sent. |
utmContent |
string, at most 120 characters | null | required | The utm_content value, at most 120 characters, or null for none. The key must be sent. |
Output #
| Field | Type | Present | Description |
|---|---|---|---|
id |
string | always | The id of the saved campaign link. Pass it to campaigns.update as id. |
key |
string | always | The utm_campaign value of the link, lower case. Traffic is matched to the saved campaign by it. |
name |
string | always | The name the campaign is listed under in the dashboard. |
baseUrl |
string | always | The address the link leads to, without the campaign tags. |
utmSource |
string | always | The utm_source value of the link. |
utmMedium |
string | null | always | The utm_medium value of the link, stored lower case, or null. |
utmTerm |
string | null | always | The utm_term value of the link, or null. |
utmContent |
string | null | always | The utm_content value of the link, or null. |
createdAt |
number | always | When the link was saved, milliseconds since 1970 UTC. |
updatedAt |
number | always | When the link was last changed, milliseconds since 1970 UTC. |
Example #
curl -s -X POST https://clearsaga.com/api/v1/campaigns.create \
-H "Authorization: Bearer $CLEARSAGA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"siteId":"site_abc123def456","key":"spring-sale","name":"Spring sale","baseUrl":"https://example.com/pricing","utmSource":"newsletter","utmMedium":"email","utmTerm":null,"utmContent":null}'clearsaga campaigns create --input '{"siteId":"site_abc123def456","key":"spring-sale","name":"Spring sale","baseUrl":"https://example.com/pricing","utmSource":"newsletter","utmMedium":"email","utmTerm":null,"utmContent":null}'Tool: campaigns_create
Arguments: {"siteId":"site_abc123def456","key":"spring-sale","name":"Spring sale","baseUrl":"https://example.com/pricing","utmSource":"newsletter","utmMedium":"email","utmTerm":null,"utmContent":null}Run clearsaga help campaigns create for one flag per field.
Delete campaign link #
POST /api/v1/campaigns.delete · Write
Removes a saved campaign link from one site for good: its name, its address and its tags. This cannot be undone. To change a link and keep it, call campaigns.update instead. The id comes from campaigns.list. Only the saved link goes. No traffic is removed: visits that arrived with its utm_campaign value stay in every report, and campaigns.breakdown keeps listing them under that value, with created null. A link that never had traffic leaves campaigns.breakdown. Links that were already handed out keep working, because the tags are part of the address itself. An id the site does not have is not an error: the answer says deleted false and nothing was changed, so sending the same call twice is safe. Needs a token with the Write permission.
Input #
| Field | Type | Required | Description |
|---|---|---|---|
siteId |
string | required | The site id, from sites.list. |
id |
string, at least 1 characters | required | The id of the saved campaign link to remove, from campaigns.list. |
Output #
| Field | Type | Present | Description |
|---|---|---|---|
id |
string | always | The id that was sent. |
deleted |
boolean | always | true when the saved campaign link was there and this call removed it. false when the site has no saved campaign link with that id, because it was removed before or the id is wrong: nothing was changed, and that is not an error. |
name |
string | null | always | The name the link was listed under, so it is clear what was removed. Null when deleted is false. |
key |
string | null | always | The utm_campaign value the link had. Its traffic stays in the reports under this value. Null when deleted is false. |
Example #
curl -s -X POST https://clearsaga.com/api/v1/campaigns.delete \
-H "Authorization: Bearer $CLEARSAGA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"siteId":"site_abc123def456","id":"CAMPAIGN_ID"}'clearsaga campaigns delete --input '{"siteId":"site_abc123def456","id":"CAMPAIGN_ID"}'Tool: campaigns_delete
Arguments: {"siteId":"site_abc123def456","id":"CAMPAIGN_ID"}Run clearsaga help campaigns delete for one flag per field.
List campaign links #
POST /api/v1/campaigns.list · Read
The saved campaign links of one site, newest first: each with its id, its key (the utm_campaign value), a name, the address it leads to and its other tags. Get the siteId from sites.list first. The whole list comes at once (a site holds at most 200); there is no paging, no range and no filter. These are definitions made in the link builder, not traffic: a campaign that was only ever seen in visits is not here. For the traffic of campaigns call campaigns.breakdown. Keeps working while the workspace is locked.
Needs a token with the Read permission. Keeps answering while the dashboards of the workspace are locked.
Input #
| Field | Type | Required | Description |
|---|---|---|---|
siteId |
string | required | The site id, from sites.list. |
Output #
| Field | Type | Present | Description |
|---|---|---|---|
rows |
array of object | always | The saved campaign links of the site, newest first: id, key (the utm_campaign value), name, baseUrl (where the link leads), utmSource, and utmMedium, utmTerm and utmContent, each a value or null. Times are milliseconds since 1970 UTC. |
Example #
curl -s -X POST https://clearsaga.com/api/v1/campaigns.list \
-H "Authorization: Bearer $CLEARSAGA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"siteId":"site_abc123def456"}'clearsaga campaigns list --input '{"siteId":"site_abc123def456"}'Tool: campaigns_list
Arguments: {"siteId":"site_abc123def456"}Run clearsaga help campaigns list for one flag per field.
Campaign totals #
POST /api/v1/campaigns.totals · Read
The headline numbers of campaign traffic on one site for a period: distinct campaigns, visitors, page views, conversions, credited orders and credited revenue, and the same for the comparison period. Get the siteId from sites.list first. Only campaign visits are counted: visits that arrived with at least one campaign tag (utm_source, utm_medium, utm_campaign, utm_term or utm_content). A conversion is a completion of an enabled conversion goal, or any custom event when the site has no enabled goal. The conversion filter is ignored by the campaign reports; every other filter applies. revenue is in minor units (cents) of revenue.currency and is null when the site never had an order. compare is null when compare is off or the range is all. For the split by campaign, source or medium call campaigns.breakdown. Answers 402 workspace_locked while the workspace's dashboards are locked.
Needs a token with the Read permission. Answers 402 while the dashboards of the workspace are locked.
Input #
| Field | Type | Required | Description |
|---|---|---|---|
siteId |
string | required | The site id, from sites.list. |
range |
"today" | "yesterday" | "30m" | "12h" | "24h" | "week" | "7d" | "30d" | "60d" | "90d" | "mtd" | "ytd" | "12mo" | "all" | "custom" | optional | The period to report on: one of today, yesterday, 30m, 12h, 24h, week, 7d, 30d, 60d, 90d, mtd, ytd, 12mo, all. Left out, the workspace's default range is used (30d unless it was changed). For exact dates send from and to and leave range out (custom is accepted with them and means the same). A preset together with dates answers 400. |
from |
string | optional | First day of a custom period, YYYY-MM-DD in the site's time zone. Send it together with to: one without the other answers 400, and so does a day that does not exist or a from after to. A day after today is read as today; window in the answer shows the period that was used. |
to |
string | optional | Last day of a custom period, inclusive, YYYY-MM-DD in the site's time zone. Send it together with from. |
compare |
"prev" | "week" | "month" | "quarter" | "year" | "custom" | "off" | optional | What the period is compared with: prev (the period just before, the default), week, month, quarter or year earlier, custom (cfrom and cto are then required), or off for no comparison. The range all never has a comparison. |
cfrom |
string | optional | First day of a custom comparison period, YYYY-MM-DD. Required with compare set to custom, where a day that does not exist or a cfrom after cto answers 400. |
cto |
string | optional | Last day of a custom comparison period, inclusive, YYYY-MM-DD. Required with compare set to custom. |
filters |
object | optional | Narrow the numbers to matching traffic. An object such as { "country": "us", "path.has": "pricing" }. A plain key means "is"; a key ending in .not means "is not" and a key ending in .has means "contains". Filters are joined with AND. At most 10 keys, of which at most 3 may end in .has. Default: {}. The filter keys are listed under Filters. |
Output #
| Field | Type | Present | Description |
|---|---|---|---|
serverNow |
number | always | The clock the period was resolved with: the start of the next whole minute, milliseconds since 1970 UTC. |
serverTime |
number | always | When the answer was built, milliseconds since 1970 UTC. |
window |
object | always | The period the numbers cover: from and to in milliseconds since 1970 UTC (to is exclusive), the time zone, a label and the bucket size. |
compare |
object | null | always | The comparison period (from, to, tz, label, granularity, token) with the same six numbers for it: campaigns, visitors, views, conversions, orders and revenue. Null when there is no comparison. |
rawFrom |
number | null | always | The earliest time detailed data is kept from, or null when nothing was trimmed. |
truncated |
boolean | always | True when a filtered answer could only cover the part of the period that still has detailed data. |
campaigns |
number | always | Distinct campaign names (utm_campaign values) seen in the period. Saved links without traffic are not counted. |
visitors |
number | always | Visitors with at least one campaign visit. |
views |
number | always | Page views in campaign visits. |
conversions |
number | always | Conversions in campaign visits. conversionMode says what counts as one. |
orders |
number | always | Orders credited to campaign visits. 0 when the site records no revenue. |
revenue |
object | null | always | Revenue credited to campaign visits as { minor, currency } in minor units (cents); multiCurrency is true when orders in other currencies exist and were left out. Null when the site never had an order. |
conversionMode |
"goals" | "events" | always | goals: conversions are completions of the enabled conversion goals. events: the site has no enabled goal, so every custom event counts. |
Example #
curl -s -X POST https://clearsaga.com/api/v1/campaigns.totals \
-H "Authorization: Bearer $CLEARSAGA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"siteId":"site_abc123def456"}'clearsaga campaigns totals --input '{"siteId":"site_abc123def456"}'Tool: campaigns_totals
Arguments: {"siteId":"site_abc123def456"}Run clearsaga help campaigns totals for one flag per field.
Update campaign link #
POST /api/v1/campaigns.update · Write
Replaces every field of a saved campaign link. Send all of them in full; utmMedium, utmTerm and utmContent as text or as null. The id comes from campaigns.list or campaigns.create. Changing the key detaches the saved link from the traffic that carried the old key, which stays listed in campaigns.breakdown on its own. The link is shown to members of the workspace in the dashboard, so only save an address they can trust: baseUrl must be an http or https address (400 invalid otherwise). An unknown id answers 404 and a key another saved link of the site uses answers 409 taken. Sending the same input twice leaves the link as it is. Needs a token with the Write permission.
Input #
| Field | Type | Required | Description |
|---|---|---|---|
siteId |
string | required | The site id, from sites.list. |
id |
string, at least 1 characters | required | The id of the saved campaign link to change, from campaigns.list. |
key |
string | required | The utm_campaign value of the link: 1 to 120 characters from lower case letters, digits, dot, underscore, tilde and hyphen. Unique among the saved links of the site. Traffic is matched to the link by it. |
name |
string, 1 to 80 characters | required | The name the campaign is listed under in the dashboard, 1 to 80 characters. |
baseUrl |
string, at most 2000 characters | required | The address the link leads to, without campaign tags. A full http or https address of at most 2,000 characters, such as the address of your pricing page. |
utmSource |
string | required | The utm_source value: where the link is placed, for example newsletter. 1 to 120 characters from lower case letters, digits, dot, underscore, tilde, hyphen and space. |
utmMedium |
string, at most 120 characters | null | required | The utm_medium value, for example email, at most 120 characters, or null for none. The key must be sent. It is stored lower case. |
utmTerm |
string, at most 120 characters | null | required | The utm_term value, at most 120 characters, or null for none. The key must be sent. |
utmContent |
string, at most 120 characters | null | required | The utm_content value, at most 120 characters, or null for none. The key must be sent. |
Output #
| Field | Type | Present | Description |
|---|---|---|---|
id |
string | always | The id of the saved campaign link. Pass it to campaigns.update as id. |
key |
string | always | The utm_campaign value of the link, lower case. Traffic is matched to the saved campaign by it. |
name |
string | always | The name the campaign is listed under in the dashboard. |
baseUrl |
string | always | The address the link leads to, without the campaign tags. |
utmSource |
string | always | The utm_source value of the link. |
utmMedium |
string | null | always | The utm_medium value of the link, stored lower case, or null. |
utmTerm |
string | null | always | The utm_term value of the link, or null. |
utmContent |
string | null | always | The utm_content value of the link, or null. |
createdAt |
number | always | When the link was saved, milliseconds since 1970 UTC. |
updatedAt |
number | always | When the link was last changed, milliseconds since 1970 UTC. |
Example #
curl -s -X POST https://clearsaga.com/api/v1/campaigns.update \
-H "Authorization: Bearer $CLEARSAGA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"siteId":"site_abc123def456","id":"CAMPAIGN_ID","key":"spring-sale","name":"Spring sale","baseUrl":"https://example.com/pricing","utmSource":"newsletter","utmMedium":"email","utmTerm":null,"utmContent":null}'clearsaga campaigns update --input '{"siteId":"site_abc123def456","id":"CAMPAIGN_ID","key":"spring-sale","name":"Spring sale","baseUrl":"https://example.com/pricing","utmSource":"newsletter","utmMedium":"email","utmTerm":null,"utmContent":null}'Tool: campaigns_update
Arguments: {"siteId":"site_abc123def456","id":"CAMPAIGN_ID","key":"spring-sale","name":"Spring sale","baseUrl":"https://example.com/pricing","utmSource":"newsletter","utmMedium":"email","utmTerm":null,"utmContent":null}Run clearsaga help campaigns update for one flag per field.