Trackily Docs

Référence : conditions

Toutes les métriques, opérateurs, fenêtres temporelles que tu peux utiliser dans une règle Automizer. Avec exemples concrets pour chaque.

Anatomie d'une condition

{
  "metric": "roi",
  "operator": "<",
  "value": -40,
  "window": "6h"
}
  • metric — la métrique à surveiller (clicks, cost, roi, etc.)
  • operator — la comparaison (>, <, =, !=, etc.)
  • value — la valeur de référence (toujours un nombre)
  • window — la fenêtre temporelle sur laquelle la métrique est calculée

Une règle a 1+ conditions, AND entre elles (toutes doivent être vraies pour trigger). Voir automizer.js:51.

Les métriques (campagnes)

Ces métriques sont calculées par getStatsForTimeWindow(campaign_id, window) (voir database.js:3354). Elles agrègent les rows clicks + conversions filtrées par campagne (si scoped) et par fenêtre.

Metric Type Calcul Notes
clicks int COUNT(*) sur clicks Total clicks bruts (humains + bots)
unique_clicks int COUNT(*) WHERE is_unique Dédup par fingerprint IP+UA
bots int COUNT(*) WHERE is_bot Clicks détectés comme bots
leads int COUNT(*) WHERE is_lead Clicks marqués comme lead par le bot filter
conversions int COUNT(*) sur conversions Total conversions (tous types)
revenue float SUM(conversions.revenue) + SUM(clicks.revenue) Total revenue ($)
cost float SUM(clicks.cost) Total cost ($) — vient de source.cost_param
profit float revenue - cost Marge brute ($)
roi float (profit / cost) * 100 En pourcent. Vaut 0 si cost=0.
cr float (conversions / unique_clicks) * 100 Conversion rate en pourcent
epc float revenue / unique_clicks Earnings per click en $
bot_rate float (bots / clicks) * 100 % bots en pourcent
fraud_score_avg float AVG(fraud_score) Score moyen 0-100

Attention à l'unité : roi, cr, bot_rate sont en pourcent (0-100+), pas en ratio (0-1). Un ROI de 150% se compare à value: 150, pas value: 1.5.

Côté DB la métrique est arrondie : roi à 1 décimale, revenue/cost/profit à 2, cr à 2, epc à 4 (voir database.js:3372).

Les métriques (produits natifs)

Si tu scopes ta règle avec product_id au lieu de campaign_id, c'est getProductStatsForTimeWindow(product_id, window) (voir database.js:3383) qui tourne. La liste est légèrement différente :

Metric Type Notes
clicks, unique_clicks, bots, leads int Idem campagnes
conversions int Toutes conversions sur les campagnes liées au produit
sales int COUNT(conversions) WHERE conversion_type='sale'
revenue, cost, profit float Idem
roi float En %
roas float revenue / cost — en ratio (pas en %)
aov float revenue / sales — Average Order Value
cr float En %
epc float En $
bot_rate float En %

Le roas est unique aux règles produit. Pour les règles campagne, utilise roi (qui couvre le même concept en %).

Les opérateurs

Le normaliseur (autopilot-actions.js:172) accepte deux formes :

Symboles (canoniques)

Symbole Sens
> strictement supérieur
< strictement inférieur
>= supérieur ou égal
<= inférieur ou égal
= égal (number equality)
!= différent

Aliases (autorisés, normalisés en symboles)

Alias → Symbole
gt >
lt <
gte >=
lte <=
eq ou equals ou == =
neq ou not_equals ou <> ou ne !=

N'importe quel autre operator → erreur Unsupported operator "X". Accepted: > < >= <= = != or gt / lt / gte / lte / eq / neq.

Les fenêtres temporelles

Le mapping (database.js:3355) :

Window string Interval Postgres
"1h" 1 hour
"2h" 2 hours
"6h" 6 hours
"12h" 12 hours
"24h" 24 hours
"3d" 3 days
"7d" 7 days

Une fenêtre inconnue (ex : "30d") est silencieusement fallback à 24 hours. Pour les besoins long-terme, agrège en upstream (rapport hebdo) — l'Automizer est fait pour des décisions réactives.

Si la condition n'a pas de window, la première condition de la règle donne sa window aux suivantes (automizer.js:42). En pratique : mets toujours window explicite sur chaque condition.

Combinaisons recommandées

Sécurité — "stop the bleeding"

{ "metric": "cost",        "operator": ">",  "value": 50,  "window": "6h" }
{ "metric": "conversions", "operator": "<",  "value": 2,   "window": "6h" }

Pause si t'as dépensé > $50 sans assez de conversions sur 6h.

Scale — "go bigger on winners"

{ "metric": "roi",         "operator": ">",  "value": 100, "window": "24h" }
{ "metric": "conversions", "operator": ">=", "value": 10,  "window": "24h" }
{ "metric": "cost",        "operator": ">=", "value": 100, "window": "24h" }

Triple garde-fou : ROI > 100%, ≥ 10 conversions, ≥ $100 spent (= signal statistiquement significatif).

Anti-fraude — "kill the bots"

{ "metric": "bot_rate", "operator": ">",  "value": 30,  "window": "6h" }
{ "metric": "clicks",   "operator": ">=", "value": 500, "window": "6h" }

Le clicks >= 500 évite les faux positifs sur du faible volume.

Detect quality drop — "EPC tank"

{ "metric": "epc",          "operator": "<",  "value": 0.05, "window": "12h" }
{ "metric": "unique_clicks","operator": ">=", "value": 1000, "window": "12h" }

EPC qui s'effondre = audience qui ne convertit plus = il est temps de changer creative / offer.

Funnel slow — "lead-to-sale ratio"

{ "metric": "leads",       "operator": ">=", "value": 50, "window": "24h" }
{ "metric": "conversions", "operator": "<",  "value": 3,  "window": "24h" }

Beaucoup de leads mais peu de conversions = problème au checkout. Trigger une notif pour aller voir.

Pièges à éviter

Unité du ROI

roi: 150 veut dire 150%, pas 1.5x. ROI de 1.5x = value: 50 (50%).

Window vs check_interval

Indépendants ! Une règle avec window: "24h" et check_interval_minutes: 5 est évaluée toutes les 5 min sur les 24h glissantes. Tu peux donc trigger plusieurs fois pour la même journée si l'action ne change pas l'état observé. Mets check_interval_minutes ≥ la durée pendant laquelle l'action a effet (ex : pause = action change immédiatement, donc 5 min OK ; scale = effet observable après 30-60 min, donc 60 min mini).

Métrique manquante

Si la métrique demandée n'a pas de valeur (cas extrême : zero click, zero conversion → certaines métriques sont 0 et d'autres undefined), getStatsForTimeWindow retourne 0 pour les agrégats (sauf roi/cr/epc qui sont 0 si cost/clicks = 0). Donc roi < -40 est faux quand cost=0 → la règle ne trigger pas. C'est intentionnel : pas d'activité = rien à faire.

= (égalité stricte)

Sur des floats, l'égalité stricte est rarement utile (roi = 50.0 ne match jamais 50.000001). Utilise des intervalles : roi >= 49 AND roi <= 51.

AND uniquement

L'engine fait AND entre conditions, pas OR (automizer.js:66). Pour exprimer un OR, fais deux règles. Exemple :

// Au lieu de "ROI < -40 OR bot_rate > 50"
Rule A : ROI < -40 → pause
Rule B : bot_rate > 50 → pause

Vérifier une condition à la main (debug)

Tu veux savoir si la métrique X de la campagne 42 sur 6h vaut bien ce que tu penses ? Le tool MCP get_stats te donne le snapshot exact :

{
  "name": "get_stats",
  "arguments": {
    "campaign_id": 42,
    "window": "6h"
  }
}

Réponse :

{
  "clicks": 1234,
  "unique_clicks": 980,
  "conversions": 12,
  "revenue": 187.50,
  "cost": 145.20,
  "profit": 42.30,
  "roi": 29.1,
  "cr": 1.22,
  "epc": 0.19,
  "bot_rate": 4.3
}

Tu peux alors évaluer ta condition mentalement : roi (29.1) < -40 → faux → la règle ne trigger pas. Ça t'évite des heures de debug "pourquoi ma règle ne déclenche pas".

Exemple complet — combo réaliste

{
  "name": "create_automizer_rule",
  "arguments": {
    "name": "Multi-gate scale rule",
    "campaign_id": 42,
    "conditions": [
      { "metric": "roi",          "operator": ">=", "value": 80,  "window": "24h" },
      { "metric": "conversions",  "operator": ">=", "value": 15,  "window": "24h" },
      { "metric": "cost",         "operator": ">=", "value": 100, "window": "24h" },
      { "metric": "bot_rate",     "operator": "<",  "value": 15,  "window": "24h" },
      { "metric": "epc",          "operator": ">=", "value": 0.20,"window": "24h" }
    ],
    "actions": [
      { "type": "meta_change_daily_budget", "value": 75 }
    ],
    "check_interval_minutes": 360
  }
}

Lecture : "Si la campagne a un ROI ≥ 80%, ≥ 15 conversions, ≥ $100 spent (signal solide), < 15% de bots (qualité OK), et EPC ≥ $0.20 (pas de creative fatigue), alors push le daily budget Meta à $75. Vérifie toutes les 6h."

Voir aussi