Find the constraint in the paid funnel
Builds the full funnel per campaign (or ad set / ad) over the requested window and returns, for each row, the step whose fix would unlock the most conversions.
The funnel is impressions → clicks → sessions → [leads] → conversions. Each step is compared against the pooled rate across every row in the account (not a global benchmark), and the constraint is the step with the highest recoverable_conversions — the extra conversions that closing the gap to that pooled rate would produce, after carrying the row's own downstream rates. A campaign already at or above the pooled rate on every step returns constraint: null: nothing to fix, scale it instead.
Supply lead_event to split the on-site step into landing (visit → lead) and sales (lead → conversion). Without it those collapse into a single site step, because sessions → conversions genuinely cannot distinguish a page problem from a closing problem.
Conversions are credited to sessions — their own when it resolved to a campaign, otherwise the person's nearest paid touch within attribution_window_days. This is effectively last-PAID-touch: an organic-session purchase by a person with a paid touch in-window is credited to paid. Pass attribution_window_days=0 for strict own-session-only credit.
Always read tracking.match_rate before trusting the rest. It is the share of ad-click sessions whose UTMs resolved to a synced Meta row; a low value means the clicks → sessions step is measuring UTM hygiene rather than landing-page quality.
curl -X GET "https://mythic-analytics.gulp.workers.dev/client/v1/constraints?location_id=example_string&from=2024-12-25&to=2024-12-25&days=28&group_by=campaign&attribution=session&conversion_event=transaction_completed&lead_event=example_string&min_impressions=1000&campaign=example_string&account_id=act_1234567890&platform=meta&revenue_path=%24.value&table=meta_ads_ads_insights_action_type&attribution_window_days=30&include=audit%2Cevents&timezone=America%2FLos_Angeles&resolve_identities=true&benchmark_ad=3.14&benchmark_tracking=3.14&benchmark_landing=3.14&benchmark_sales=3.14&benchmark_site=3.14" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN"
import requests
import json
url = "https://mythic-analytics.gulp.workers.dev/client/v1/constraints?location_id=example_string&from=2024-12-25&to=2024-12-25&days=28&group_by=campaign&attribution=session&conversion_event=transaction_completed&lead_event=example_string&min_impressions=1000&campaign=example_string&account_id=act_1234567890&platform=meta&revenue_path=%24.value&table=meta_ads_ads_insights_action_type&attribution_window_days=30&include=audit%2Cevents&timezone=America%2FLos_Angeles&resolve_identities=true&benchmark_ad=3.14&benchmark_tracking=3.14&benchmark_landing=3.14&benchmark_sales=3.14&benchmark_site=3.14"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
response = requests.get(url, headers=headers)
print(response.json())
const response = await fetch("https://mythic-analytics.gulp.workers.dev/client/v1/constraints?location_id=example_string&from=2024-12-25&to=2024-12-25&days=28&group_by=campaign&attribution=session&conversion_event=transaction_completed&lead_event=example_string&min_impressions=1000&campaign=example_string&account_id=act_1234567890&platform=meta&revenue_path=%24.value&table=meta_ads_ads_insights_action_type&attribution_window_days=30&include=audit%2Cevents&timezone=America%2FLos_Angeles&resolve_identities=true&benchmark_ad=3.14&benchmark_tracking=3.14&benchmark_landing=3.14&benchmark_sales=3.14&benchmark_site=3.14", {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
)
func main() {
req, err := http.NewRequest("GET", "https://mythic-analytics.gulp.workers.dev/client/v1/constraints?location_id=example_string&from=2024-12-25&to=2024-12-25&days=28&group_by=campaign&attribution=session&conversion_event=transaction_completed&lead_event=example_string&min_impressions=1000&campaign=example_string&account_id=act_1234567890&platform=meta&revenue_path=%24.value&table=meta_ads_ads_insights_action_type&attribution_window_days=30&include=audit%2Cevents&timezone=America%2FLos_Angeles&resolve_identities=true&benchmark_ad=3.14&benchmark_tracking=3.14&benchmark_landing=3.14&benchmark_sales=3.14&benchmark_site=3.14", nil)
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://mythic-analytics.gulp.workers.dev/client/v1/constraints?location_id=example_string&from=2024-12-25&to=2024-12-25&days=28&group_by=campaign&attribution=session&conversion_event=transaction_completed&lead_event=example_string&min_impressions=1000&campaign=example_string&account_id=act_1234567890&platform=meta&revenue_path=%24.value&table=meta_ads_ads_insights_action_type&attribution_window_days=30&include=audit%2Cevents&timezone=America%2FLos_Angeles&resolve_identities=true&benchmark_ad=3.14&benchmark_tracking=3.14&benchmark_landing=3.14&benchmark_sales=3.14&benchmark_site=3.14')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
response = http.request(request)
puts response.body
{
"success": true,
"data": {
"window": {
"from": "2024-12-25",
"to": "2024-12-25",
"timezone": "example_string",
"timezone_source": "request",
"ads_synced_at": "2024-12-25T10:00:00Z",
"last_day_complete": true,
"note": "example_string"
},
"grain": "campaign",
"campaign": "example_string",
"attribution": "session",
"conversion_event": "example_string",
"lead_event": "example_string",
"revenue_measured": true,
"steps": [
{
"step": "ad",
"from": "example_string",
"to": "example_string"
}
],
"benchmarks": {},
"benchmark_sources": {},
"pooled_rates": {},
"pooled_rates_all_rows": {},
"benchmark_pool_rows": 42,
"stored_benchmarks": {
"default": {},
"default_notes": {},
"campaigns": [
{
"campaign": "example_string",
"benchmarks": {},
"notes": {},
"matched_rows": 42
}
],
"not_applicable_steps": [
"example_string"
],
"not_applicable_reason": "example_string"
},
"stored_benchmarks_unavailable": "example_string",
"tracking": {
"matched_sessions": 42,
"unmatched_sessions": 42,
"match_rate": 3.14,
"joined_by_id": 123,
"joined_by_url_param": 42,
"grain_resolvable": true,
"joined_by_name": 42,
"click_to_session_rate": 3.14,
"unique_clicks": 42,
"click_to_unique_click_rate": 3.14,
"meta_reported": {
"landing_page_views": 25,
"leads": 42,
"sessions_per_landing_page_view": 3.14,
"our_lead_sessions": 42,
"our_leads_per_meta_lead": 3.14,
"our_converting_sessions": 42,
"our_conversions_per_meta_lead": 3.14
},
"redirect": {
"used": true,
"unavailable": "example_string",
"hits": 42,
"unique_clicks": 42,
"rows_with_redirect": 42,
"click_to_redirect_rate": 3.14,
"redirect_to_visit_rate": 3.14,
"by_placement": {}
},
"unexpanded_macro": {
"sessions_all_sources": 42,
"sessions_in_unmatched": 42,
"sessions": 42,
"meta_click_sessions": 42,
"sample": "example_string",
"message": "example_string"
}
},
"conversion_attribution": {
"window_days": 42,
"identity": "distinct_id",
"total_conversions_in_window": 42,
"credited_via_session": 42,
"credited_via_person": 42,
"uncredited": 42,
"credited_coverage": 3.14,
"identity_resolution": {
"enabled": true,
"conversions_resolved_to_person": 42,
"conversions_resolved_rate": 3.14,
"distinct_converting_persons": 42
}
},
"diagnostic": {
"code": "no_campaign_data",
"message": "example_string"
},
"audit": {},
"event_inventory": {},
"auto_selected": {
"conversion_event": "transaction_completed",
"lead_event": "input_captured",
"revenue_path": "$.meta_amount",
"chosen_from": 20
},
"warning": {
"code": "low_conversion_coverage",
"message": "example_string"
},
"account_id": "example_string",
"diagnostics_scope": "location",
"account_totals": {
"rows": 42,
"impressions": 42,
"clicks": 42,
"spend": 3.14,
"meta_landing_page_views": 25,
"meta_leads": 42,
"sessions": 42,
"unique_clicks": 42,
"lead_sessions": 42,
"converting_sessions": 42,
"conversions": 42,
"revenue": 3.14,
"cost_per_conversion": 3.14,
"roas": 3.14
},
"excluded_low_volume": 42,
"min_impressions": 42,
"rows": [
{
"campaign_id": "example_string",
"campaign_name": "John Doe",
"account_id": "example_string",
"impressions": 42,
"clicks": 42,
"spend": 3.14,
"meta_landing_page_views": 25,
"meta_leads": 42,
"sessions": 42,
"unique_clicks": 42,
"lead_sessions": 42,
"converting_sessions": 42,
"conversions": 42,
"revenue": 3.14,
"top_landing_page": "example_string",
"redirect": {
"hits": 42,
"unique_clicks": 42,
"click_to_redirect_rate": 3.14,
"redirect_to_visit_rate": 3.14,
"by_placement": {}
},
"placements": [
{
"placement": "example_string",
"spend": 3.14,
"impressions": 42,
"clicks": 42,
"landing_page_views": 25,
"leads": 42,
"ctr": 3.14,
"cost_per_click": 3.14,
"cost_per_lead": 3.14,
"redirect_unique_clicks": 42,
"click_to_redirect_rate": 3.14
}
],
"cpa": 3.14,
"roas": 3.14,
"funnel": {},
"benchmarks": {},
"benchmark_sources": {},
"creative": {
"is_representative": true,
"headline": "example_string",
"body": "example_string",
"description": "example_string",
"call_to_action": "example_string",
"destination_url": "example_string",
"effective_destination_url": "example_string",
"display_url": "example_string",
"url_tags": "example_string",
"image_url": "example_string",
"video_id": "example_string",
"format": "image",
"asset_count": 10,
"assets": [
{
"headline": "example_string",
"body": "example_string",
"image_url": "example_string",
"link": "example_string"
}
],
"unavailable": "example_string",
"reason_code": "creative_not_synced"
},
"converting_persons": 42,
"person_ids": [
"example_string"
],
"measurable": {},
"status": "constrained",
"constraint": {
"step": "ad",
"diagnosis": "example_string",
"rate": 3.14,
"benchmark_rate": 3.14,
"benchmark_source": "override",
"benchmark_note": "example_string",
"confidence": "low",
"confidence_reason": "example_string",
"rate_vs_benchmark": 3.14,
"recoverable_conversions": 3.14,
"sub_step": "delivery",
"sub_step_diagnosis": "example_string"
}
}
],
"placements": {},
"summary": {
"primary_constraint": {
"step": "example_string",
"diagnosis": "example_string",
"recoverable_conversions": 3.14,
"entities": 42,
"spend": 3.14
},
"by_step": [
{}
]
}
}
}
{
"error": "Bad Request",
"message": "The request contains invalid parameters or malformed data",
"code": 400,
"details": [
{
"field": "email",
"message": "Invalid email format"
}
]
}
{
"error": "Unauthorized",
"message": "Authentication required. Please provide a valid API token",
"code": 401
}
{
"error": "Unprocessable Entity",
"message": "The request was well-formed but contains semantic errors",
"code": 422,
"details": [
{
"field": "password",
"message": "Password must be at least 8 characters long"
}
]
}
{
"error": "Error",
"message": "No synced Meta ads-insights table for this client yet (connect Meta through the Airbyte API and let its first sync finish, or pass `?table=`).
",
"code": 424
}
{
"error": "Too Many Requests",
"message": "Rate limit exceeded. Please try again later",
"code": 429,
"retryAfter": 3600
}
{
"error": "Error",
"message": "`platform=google` — Google Ads is not supported yet (`platform_not_supported`).",
"code": 501
}
{
"error": "Service Unavailable",
"message": "The service is temporarily unavailable. Please try again later",
"code": 503
}
/client/v1/constraints
Target server for requests. Edit to use your own host.
Agency key (ak_) or location secret key (sk_). Scoped keys (mcp_) are accepted too and need constraints:read or constraints:write. See Using an mcp_ key over HTTP.
ak_) or location secret key (sk_). Scoped keys (mcp_) are accepted too and need constraints:read or constraints:write. See Using an mcp_ key over HTTP.Location to scope to. Required for ak_ keys (or send the X-Location-Id header); ignored for sk_.
Window start (YYYY-MM-DD). Defaults to 28 days before to.
Window end (YYYY-MM-DD), inclusive. Defaults to yesterday.
Window length in days, inclusive of both ends — the same shorthand /client/v1/data takes. days=90 ending yesterday is the usual call. Ignored when from is given explicitly. Out-of-range values are rejected, not clamped.
Grain of the analysis. ad is where creative lives, but it matches through utm_content, which carries a usable ad identifier on far fewer accounts than utm_id does — expect a lower match_rate.
session uses the conversion's own session's campaign when it has one, else the person's MOST RECENT paid touch in the window — effectively last-paid-touch, closest to what the ad platform itself would claim. first_touch uses the person's EARLIEST paid touch: the campaign that first acquired them, however long ago.
Event name counted as the conversion. Discover this client's real event names via GET /client/v1/data/events/breakdown?dimension=event_name.
Pass `auto` to let the endpoint choose: it runs the eligibility probe first, takes its suggested pairing, and reports the choice under auto_selected so it is visible rather than magic. That replaces a round trip you would otherwise make to /constraints/events purely to learn which event to ask about. An explicit lead_event still wins over the suggestion. If nothing in the window can serve as a conversion you get a 422 no_usable_conversion_event rather than an analysis of a dead funnel.
Optional mid-funnel event. Supplying it splits the on-site step into landing and sales. Must differ from conversion_event.
Rows below this many impressions are excluded from the analysis but still counted in the pooled benchmarks — dropping them from the pool would inflate the bar the surviving rows are judged against.
Drill into one campaign, matched by campaign id or name (trimmed, case-insensitive). With group_by=adset or ad it scopes the rows to that campaign's children. Benchmarks stay the account-wide pooled rates, so the campaign is still judged against the whole account — that comparison is the point of the drilldown. If nothing matches, the response carries a campaign_not_found diagnostic instead of a silent empty list.
Return only one Meta ad account's rows: the numeric id, with or without the act_ prefix Ads Manager shows (act_1234567890 and 1234567890 are the same filter). Anything else is a 400.
The filter runs after attribution. Conversions are credited across every ad account in the location first, then the rows are filtered, so a person who clicked an ad in account A and later one in account B is credited once, to whichever touch the attribution model picks, and never to both accounts. Benchmarks, pooled_rates, tracking, conversion_attribution and any diagnostic stay location-wide; the response says so with diagnostics_scope: location and adds account_totals. Combine with campaign to narrow further. If the account has no rows in the window the response carries an account_not_found diagnostic.
Ad platform. Only meta is supported; google answers 501 platform_not_supported until a Google Ads adapter exists.
JSON path to the conversion's monetary value inside the event's properties. properties_json is the properties object, so the path is $.value, not $.properties.value.
Pass none when the conversion event carries no value (the /constraints/events inventory lists each event's revenue_paths). Revenue is then not read at all: revenue is 0, roas is null and revenue_measured is false. Reading the properties is most of the scan on a small client (measured: 4.2 of 7.1 GB), so this makes the call cheaper and faster. conversion_event=auto does this by itself when the event it picks has no value path.
Meta insights table in the client's dataset, if it differs from the platform default.
How long after a campaign touch a conversion may still be credited to it. A conversion with no session of its own (all CRM/server-side conversions) is credited to the person's nearest campaign touch inside this window; touches are looked up back to from minus the window, so early-window conversions still find the visit that earned them. Meta's own default is 7-day click — pass 7 for numbers comparable to Ads Manager. Pass 0 for strict own-session credit only (disables person crediting; the conservative reading).
Comma-separated optional sections, all off by default: include=creative,audit,events,placements.
creative adds each row's ad copy, destination and assets. Off by default because it is not free: measured on one client it scans 285.9 MB on every call at every grain, independent of the report window (the creatives table sits in a single partition that nothing prunes, and one JSON column is 139 MB of it). If you join creative yourself, leave it off. Row labels are unaffected — ad_name comes from ads-insights and top_landing_page from sessions.
audit returns the tracking-hygiene report (the same body as /constraints/audit) under an audit key, and events returns the event inventory (/constraints/events) under event_inventory. These stay separate BigQuery jobs — one request cannot make them one scan — but they run in parallel with the analysis, so a caller that needed all three stops paying three serial round trips and pays the slowest one instead.
placements splits every row by Meta placement (facebook, instagram, audience_network, messenger, threads) with spend, impressions, link clicks, Meta landing page views and Meta leads, and rolls the account up by placement under a top-level placements. Audience Network behaves unlike the rest (measured on one account: 71% of clicks, a 37% click rate, no leads), and summed into a row it reads as a healthy ad with a weak page. Needs the ads_insights_delivery_platform stream on the Meta connection; without it the section is {"unavailable": "stream_not_synced"}.
A section that fails is reported as {"unavailable": "<reason>"} inside a 200; the analysis itself is never failed by it. An unknown name is a 400 rather than a silent omission.
IANA time zone the funnel's days are bucketed in, e.g. America/Los_Angeles. Meta reports in the ad account's time zone (its date_start is that account's local day), so our events are moved onto the same calendar; left to UTC, a Pacific account's evening clicks land on the next day on one side only (measured: a day of 13 clicks read as 22 in UTC).
Default: the location's stored time zone, else UTC. The response states the zone used in window.timezone and where it came from in window.timezone_source. Also sets the default to (yesterday in that zone). An unknown name is a 400.
Identity stitching — resolve people through the central identity snapshots (merge tombstones collapsed) rather than the raw distinct_id. On by default, and you almost never want it off.
A CRM/server-side conversion arrives with no session of its own, so credit can only reach a campaign through the person; the conversion's distinct_id is a CRM contact id that shares nothing with the browsing device's id until the snapshot maps both onto one person. Measured on one client over 30 days (273 conversions): the raw distinct_id could credit 10% of conversions to a paid touch, canonical persons credited 81%.
Pass false (or 0) to opt out — useful only to reproduce a figure from before this was the default. conversion_attribution.identity_resolution reports how much of the resolution actually worked.
Target rate for the impressions -> clicks step, replacing the account's pooled rate. A rate between 0 and 1 — a 2% CTR target is 0.02. Values above 1 are rejected, not interpreted as percentages.
Target rate for the clicks -> sessions step. Rate between 0 and 1.
Target rate for the sessions -> leads step. Rate between 0 and 1. Requires lead_event; without it this step does not exist and the request is rejected.
Target rate for the leads -> conversions step. Rate between 0 and 1. Requires lead_event.
Target rate for the combined sessions -> conversions step. Rate between 0 and 1. Only valid WITHOUT lead_event, which splits this step into landing and sales.
Request Preview
Response
Response will appear here after sending the request
Authentication
Bearer token. Agency key (ak_) or location secret key (sk_). Scoped keys (mcp_) are accepted too and need constraints:read or constraints:write. See Using an mcp_ key over HTTP.
Query Parameters
Location to scope to. Required for ak_ keys (or send the X-Location-Id header); ignored for sk_.
Window start (YYYY-MM-DD). Defaults to 28 days before to.
Window end (YYYY-MM-DD), inclusive. Defaults to yesterday.
Window length in days, inclusive of both ends — the same shorthand /client/v1/data takes. days=90 ending yesterday is the usual call. Ignored when from is given explicitly. Out-of-range values are rejected, not clamped.
Grain of the analysis. ad is where creative lives, but it matches through utm_content, which carries a usable ad identifier on far fewer accounts than utm_id does — expect a lower match_rate.
campaignadsetadsession uses the conversion's own session's campaign when it has one, else the person's MOST RECENT paid touch in the window — effectively last-paid-touch, closest to what the ad platform itself would claim. first_touch uses the person's EARLIEST paid touch: the campaign that first acquired them, however long ago.
sessionfirst_touchEvent name counted as the conversion. Discover this client's real event names via GET /client/v1/data/events/breakdown?dimension=event_name.
Pass auto to let the endpoint choose: it runs the eligibility probe first, takes its suggested pairing, and reports the choice under auto_selected so it is visible rather than magic. That replaces a round trip you would otherwise make to /constraints/events purely to learn which event to ask about. An explicit lead_event still wins over the suggestion. If nothing in the window can serve as a conversion you get a 422 no_usable_conversion_event rather than an analysis of a dead funnel.
Optional mid-funnel event. Supplying it splits the on-site step into landing and sales. Must differ from conversion_event.
Rows below this many impressions are excluded from the analysis but still counted in the pooled benchmarks — dropping them from the pool would inflate the bar the surviving rows are judged against.
Drill into one campaign, matched by campaign id or name (trimmed, case-insensitive). With group_by=adset or ad it scopes the rows to that campaign's children. Benchmarks stay the account-wide pooled rates, so the campaign is still judged against the whole account — that comparison is the point of the drilldown. If nothing matches, the response carries a campaign_not_found diagnostic instead of a silent empty list.
Return only one Meta ad account's rows: the numeric id, with or without the act_ prefix Ads Manager shows (act_1234567890 and 1234567890 are the same filter). Anything else is a 400.
The filter runs after attribution. Conversions are credited across every ad account in the location first, then the rows are filtered, so a person who clicked an ad in account A and later one in account B is credited once, to whichever touch the attribution model picks, and never to both accounts. Benchmarks, pooled_rates, tracking, conversion_attribution and any diagnostic stay location-wide; the response says so with diagnostics_scope: location and adds account_totals. Combine with campaign to narrow further. If the account has no rows in the window the response carries an account_not_found diagnostic.
act_1234567890Ad platform. Only meta is supported; google answers 501 platform_not_supported until a Google Ads adapter exists.
metagoogleJSON path to the conversion's monetary value inside the event's properties. properties_json is the properties object, so the path is $.value, not $.properties.value.
Pass none when the conversion event carries no value (the /constraints/events inventory lists each event's revenue_paths). Revenue is then not read at all: revenue is 0, roas is null and revenue_measured is false. Reading the properties is most of the scan on a small client (measured: 4.2 of 7.1 GB), so this makes the call cheaper and faster. conversion_event=auto does this by itself when the event it picks has no value path.
Meta insights table in the client's dataset, if it differs from the platform default.
How long after a campaign touch a conversion may still be credited to it. A conversion with no session of its own (all CRM/server-side conversions) is credited to the person's nearest campaign touch inside this window; touches are looked up back to from minus the window, so early-window conversions still find the visit that earned them. Meta's own default is 7-day click — pass 7 for numbers comparable to Ads Manager. Pass 0 for strict own-session credit only (disables person crediting; the conservative reading).
Comma-separated optional sections, all off by default: include=creative,audit,events,placements.
creative adds each row's ad copy, destination and assets. Off by default because it is not free: measured on one client it scans 285.9 MB on every call at every grain, independent of the report window (the creatives table sits in a single partition that nothing prunes, and one JSON column is 139 MB of it). If you join creative yourself, leave it off. Row labels are unaffected — ad_name comes from ads-insights and top_landing_page from sessions.
audit returns the tracking-hygiene report (the same body as /constraints/audit) under an audit key, and events returns the event inventory (/constraints/events) under event_inventory. These stay separate BigQuery jobs — one request cannot make them one scan — but they run in parallel with the analysis, so a caller that needed all three stops paying three serial round trips and pays the slowest one instead.
placements splits every row by Meta placement (facebook, instagram, audience_network, messenger, threads) with spend, impressions, link clicks, Meta landing page views and Meta leads, and rolls the account up by placement under a top-level placements. Audience Network behaves unlike the rest (measured on one account: 71% of clicks, a 37% click rate, no leads), and summed into a row it reads as a healthy ad with a weak page. Needs the ads_insights_delivery_platform stream on the Meta connection; without it the section is {"unavailable": "stream_not_synced"}.
A section that fails is reported as {"unavailable": "<reason>"} inside a 200; the analysis itself is never failed by it. An unknown name is a 400 rather than a silent omission.
audit,eventsIANA time zone the funnel's days are bucketed in, e.g. America/Los_Angeles. Meta reports in the ad account's time zone (its date_start is that account's local day), so our events are moved onto the same calendar; left to UTC, a Pacific account's evening clicks land on the next day on one side only (measured: a day of 13 clicks read as 22 in UTC).
Default: the location's stored time zone, else UTC. The response states the zone used in window.timezone and where it came from in window.timezone_source. Also sets the default to (yesterday in that zone). An unknown name is a 400.
America/Los_AngelesIdentity stitching — resolve people through the central identity snapshots (merge tombstones collapsed) rather than the raw distinct_id. On by default, and you almost never want it off.
A CRM/server-side conversion arrives with no session of its own, so credit can only reach a campaign through the person; the conversion's distinct_id is a CRM contact id that shares nothing with the browsing device's id until the snapshot maps both onto one person. Measured on one client over 30 days (273 conversions): the raw distinct_id could credit 10% of conversions to a paid touch, canonical persons credited 81%.
Pass false (or 0) to opt out — useful only to reproduce a figure from before this was the default. conversion_attribution.identity_resolution reports how much of the resolution actually worked.
Target rate for the impressions -> clicks step, replacing the account's pooled rate. A rate between 0 and 1 — a 2% CTR target is 0.02. Values above 1 are rejected, not interpreted as percentages.
Target rate for the clicks -> sessions step. Rate between 0 and 1.
Target rate for the sessions -> leads step. Rate between 0 and 1. Requires lead_event; without it this step does not exist and the request is rejected.
Target rate for the leads -> conversions step. Rate between 0 and 1. Requires lead_event.
Target rate for the combined sessions -> conversions step. Rate between 0 and 1. Only valid WITHOUT lead_event, which splits this step into landing and sales.