Recommendations and alerts
X3 does not guess. Every recommendation comes from a fixed rule with minimum amounts, shows the numbers behind it and says how sure it is. Alerts tell you when something is broken or worth a look.
Recommendations
GET /v1/projects/{project}/recommendations (scopes analytics:read + ads:read; MCP
recommendations_list). The Pulse shows up to five; for the standard periods (7d, this_week,
30d) they are precomputed by the insights.alerts job, other periods are computed on request.
Minimums: at least 3 leads or 300 € spend in the period. Campaigns in their learning phase (first
spend less than 7 days ago or fewer than 50 clicks) never give budget away. Periods shorter than
7 days are evaluated on the last 14 days, and the recommendation says so in basis.
| Rule | When | Suggests |
|---|---|---|
shift_budget | Campaign A takes at least twice its share of leads in budget and costs ≥ 1.8× the median cost per lead (or has no lead at ≥ 2× the median); campaign B brings ≥ 3 leads at ≤ 0.7× the median, half of them qualified | Move about half of A's spend to B; expected extra leads per week with a range |
scale_winner | B is cheap (≤ 0.7× median), ≥ 3 leads, ≥ 2 qualified, budget forecast below 90 % | Raise B's budget by up to 30 % |
check_spend_no_leads | A spent ≥ max(500 €, 3× median) without a lead under all six counting rules | Check landing page, form and audience |
fix_funnel_step | One step loses ≥ 1.4× as many visitors as before and ≥ 10 points more, with ≥ 50 entries | The step and the leads lost per week |
swap_creative | Meta video ad whose hook rate (3-second views ÷ impressions) is below 0.6× the campaign median, ≥ 150 € and ≥ 1,000 impressions | Replace the ad |
connect_costs | ≥ 50 paid visits in 30 days from a platform without a connected ad account | Connect the account |
map_unmatched | ≥ 50 paid visits (or ≥ 10 %) that match no ad | Map them so cost per lead is right |
fix_reporting | Conversion uploads failing, access expired or pending for more than an hour | Fix the reporting access |
How sure: the trigger uses the active counting rule; the direction is then checked under all six. High = holds in 6 of 6, ≥ 10 leads and ≥ 75 % surely assigned; medium = ≥ 4 of 6 or 5–9 leads; low otherwise (not shown in the Pulse). If campaign A was the first contact for many leads, the recommendation says so and moves only half.
Feedback: POST …/recommendations/{id}/feedback with done, later (until Monday), dismiss
(hidden for 14 days, optional reason) or undo – scope ads:write; MCP recommendations_feedback.
Done starts an impact measurement after 7 days that appears in the weekly report ("Since done: +3
leads, 168 € per lead").
Alerts
GET /v1/alerts (all your projects) and GET /v1/projects/{project}/alerts, scope analytics:read;
MCP alerts_list. Alerts are tasks: every change that can affect one (budget
saved, account connected, sync finished, upload result, lead status, goal changed) re-checks it right
away, the job tasks.evaluate every 15 minutes is the fallback. Texts always use the current numbers.
An alert whose condition is gone resolves itself (auto_resolved, with reason and time); discrete
states (connections, goals, sync) at once, numbers with a band against flickering (budget over: opens
at 103 %, resolves below 101 %). The answer also carries resolvedByKind, occurrence, reason and
reopenLabel.
| Rule | Type | When |
|---|---|---|
no_leads | problem | No lead for much longer than usual while visits continue |
tracking_down | problem | No events for hours during the day on a site that normally has traffic |
cpl_spike | problem | Cost per lead of the last 7 days ≥ +50 % against the 7 days before (≥ 3 leads in both) |
reporting_failed | attention | Leads not reported to an ad platform |
cost_sync_stale | attention | Costs of an active account not refreshed for 6 hours |
search_console_problem | attention | The Search Console connection expired, the property refused access, or the sync failed or is overdue. Closes itself as soon as the connection works again (no 24-hour wait) |
budget_over / budget_under | attention | From day 7: forecast above 103 % / below 85 % of the monthly budget |
opportunity | opportunity | The top recommendation with high confidence |
connect_costs | setup | Paid visits from a platform without costs |
goal_never | setup | A goal never reached 7 days after it was created |
record_week | info | Most leads in 12 weeks |
traffic_drop / traffic_spike | attention / info | Yesterday's visits outside the band of the last 6 same weekdays (median ± 2.5 MAD, expected ≥ 20; a drop also under 70 % of the median), naming the source that moved most. Quiet while tracking is down and in the first days after the measuring start |
The mail of traffic_drop shows yesterday, the usual value and the visits without ads side by side,
the strongest source, „Verlauf ansehen“ and, when an ad channel moved most, „{Kanal} Kampagne
prüfen“. The X3 App pushes it as „Weniger Besuche als üblich“, sharing the daily limit with its own
hourly drop detection: at most one drop push per project and day.
Order: problem › attention › opportunity › setup › info, then by money at stake, then age.
Who sees what: viewers and clients see problems, attention (except budget), setup and info.
Budget alerts, opportunities and connect_costs are agency-internal: they need ads:read and
config:write. Closing, snoozing or reopening (PATCH /v1/alerts/{id}, MCP alerts_update) needs
config:write or ads:write.
Organization notices
Some hints concern a person or the whole organization instead of a project. GET /v1/notices (scope
analytics:read, signed-in people only) evaluates them live on every read, so they never show stale
numbers, and they resolve themselves when the condition is gone. Notices are tasks of scope person
or org (Tasks). Each notice has a scope:
person notices appear once for the signed-in person, however many organizations they belong to
(orgId, orgSlug, orgName are null); org notices appear once per organization.
| Key | Scope | Type | When | Resolves itself when |
|---|---|---|---|---|
connect_ai | person | info | You have no AI client connected yet | you connect Claude, ChatGPT or another MCP client (OAuth, any organization), or a key you created is used over MCP |
A resolved notice comes back when the condition holds again (for example every AI client of yours was
removed). Später (snooze, default tomorrow 08:00), Passt nicht (dismiss, stays hidden) and
reopen: PATCH /v1/notices/{key} for a personal notice (only for you, every role), PATCH
/v1/orgs/{org}/notices/{key} for an organization notice (shared for the organization, needs
config:write). Other members keep their own personal notices. The cockpit shows them in Braucht
Dich with a link to the connect card (ChatGPT, Gemini and other apps); the
same organization notice of several organizations becomes one card („· 5 Kunden“).
Delivery
- In the app: always.
- E-mail right away: only problems, at most one mail per project and rule in 24 hours, to members who see that alert type and did not turn it off (Alerts & reports).
- Weekly digest: Monday 08:00 in each user's time zone – all projects the user sees, numbers with change, what needs them, what was done and what it brought. The only mail that spans organizations.
- Weekly client report: per organization, to members you choose (
POST /v1/orgs/{org}/client-reportwithpreview,send_noworweekly, scopeorg:admin). Never other clients, portfolio sums or agency-internal alerts; inquiries by first name and initial or "Anfrage #n", never contact data; each recipient gets their language.
Demo projects show alerts but never send mail.