Combo rules
Combine several tags into one aggregate tag, and choose whether the conditions must be met anywhere on the scan or within a single link.
A combo rule fires on a combination of other tags and assigns one aggregate tag of its own. It turns several weak signals into a single decision — "five antivirus vendors agree", "a prohibited keyword and a redirect through a flagged domain".
Combo is one of the detection rule types. A combo's output tag can feed another combo, so aggregates can be chained.
Match scope
One scan usually covers several links — the creative, every hop of the redirect chain, the landing. Match scope decides whether conditions are counted across all of them or link by link. In the rule form it is its own field, immediately above Conditions:
- Across the whole scan (any links) (
"match_scope": "scan") — "Tags from different links of the scan can add up to satisfy the conditions." This is the default, and what rules authored before the setting existed do. - Within a single link (all conditions on one URL)
(
"match_scope": "url") — "Every condition must be satisfied by tags on the same link, and the tag is assigned to that link. A rule built only from link-less tags (AI, behaviour) has no link to attach to and will never match — keep those on the whole scan."
{ "match_scope": "url", "tag_category": "antivirus", "count_gte": 5 }
Existing rules are unchanged: a rule saved without match_scope is
evaluated exactly as before — an absent key means the whole scan. A value
that is neither "scan" nor "url" is rejected with 422 and the error
code checking.combo_match_scope_invalid (see
Authentication for the error body).
Link-less tags
Some tags describe the scan as a whole rather than one link — AI
verdicts, crawler behaviour signals. Under "url" they are treated as
context available on every link, so they never block a rule that also
requires a per-link detection. But they carry no link of their own, so a
rule built only from link-less tags has no group to fire in and will
never match under "url". Keep those rules on the whole scan.
One current limitation is worth knowing before you combine the two: AI verdicts and per-link detections (domain reputation, content and URL matches) are produced by different stages of a scan and are not evaluated together today, under either scope. A combo that mixes them will not fire until that changes. Combos over per-link detections — several antivirus vendors, a domain verdict plus a content match — are evaluated together as normal.
Conditions
A rule holds one or more conditions and fires only when all of them
hold. Over the API (POST /api/v1/custom-rules) they are keys of the
rule's config object:
| Condition | config keys | Holds when |
|---|---|---|
| All of | all_of | every listed tag is present |
| Any of | any_of, any_of_min | at least any_of_min of the listed tags are present (default 1) |
| Category count | tag_category, count_gte | count_gte or more distinct tags of that category are present |
| None of | none_of | none of the listed tags is present |
| None of category | none_of_category | no tag of that category is present |
Thresholds are always "N or more".
Under "url" the exclusions are evaluated per link too: a none_of or
none_of_category tag sitting on another link does not suppress the
rule. That can make a rule fire more often on a single link than the
same rule set to the whole scan, where one excluded tag anywhere
suppresses it everywhere.
Exclusions only narrow, so a per-link rule needs at least one positive
condition — all_of, any_of, or a category count — to mean anything. A
rule listing nothing but none_of / none_of_category has no detection
to locate and simply matches every link that lacks the excluded tags.
A rule with an exclusion waits until every scan stage able to produce an excluded tag has finished, so its tag can appear later than the tags of rules without exclusions. It never fires on an absence a later stage could still disprove.
An input whose tag has been archived is out of service and is never assigned to a scan, so a rule that requires it cannot fire while that input stays archived. The editor warns you when a rule references one. See Tags → Archiving a tag.
Choosing a scope
Pick "url" when the conditions only mean something together on one
address — vendor consensus, or "this link is both newly registered and
serving a download". Pick "scan" when the signals describe the ad as a
whole and may legitimately land on different links — an AI verdict plus a
blacklisted domain somewhere in the chain — and for any rule built only
from link-less tags.
Example: antivirus consensus
{ "tag_category": "antivirus", "count_gte": 5 } means "five antivirus
vendors flagged something".
- Under
"scan", three vendors flagging a redirect hop plus two flagging an unrelated tracker on another domain add up to five. The tag fires even though no single link was called malicious by more than three vendors. - Under
"url", the five detections have to land on the same link. The 3 + 2 split no longer fires; five vendors on one hop do, and the tag is attached to that hop.
Which reading you want is a per-rule decision, so the scope is yours to set on the rules you author. Kaminari Ad's own built-in aggregates are not affected by the setting — they keep counting across the whole scan until an administrator changes their scope.
What "url" does and does not guarantee
Links are matched as exact URLs. …?a=1 and …?a=2 are different
links, and two vendors that flagged different files on the same host land
in different groups. A host five vendors dislike can therefore miss the
threshold in every group if some of those verdicts are per-file rather
than per-host. Verdicts issued about a domain are spread across all of
that host's links, so they do add up on the hop itself — which is why the
redirect-chain hop is usually the group that fires. Grouping by domain
rather than by URL is the natural next step for cases like this; it does
not exist yet.
The guarantee is not transitive. match_scope is a property of one
rule. If a "url" rule consumes the output of a "scan" rule, the
parent's conditions are satisfied on one link, but the child's were not:
the intermediate aggregate was allowed to add tags up across links, and
it is assigned to every link that contributed. "All conditions on one
link" holds fully only for rules built on raw detections, or on
intermediates that are themselves "url"-scoped. Check the scope of the
whole chain, not just the rule you are editing.
The tag is assigned to the group's link, not preferentially to the redirect hop. In practice that is usually the hop, because the hop's group is the richest one. But when the matching link is a sub-request, the tag is shown inside that sub-request's subtree, and if the link is not part of the rendered request tree at all (the tree is capped in depth and breadth, and filters some resource types) the tag will not appear in the tree — the host still shows up in the per-tag host list.
Testing and rechecking
Test rule evaluates a draft combo against the tags of a scan you pick, which is the quickest way to confirm a scope change still catches the cases you care about. It reports whether the rule fires, not which link it fired on.
A scope change applies to scans checked from that point on. To apply it to earlier results, recheck them — with one caveat: a recheck re-runs the checks without re-crawling, so it works from less material than the first pass did. The scan's full request list is not reproduced, and the reputation sources lose ground unevenly: those that read only that list contribute nothing, those that combine the redirect chain with it still cover the chain but no longer reach hosts that appeared only in sub-requests, and only the sources working purely from the redirect chain are unaffected. Behaviour tags are cleared by the recheck and are not regenerated either, so a rule that leans on them cannot match on a rechecked scan. Fewer tags on the second pass is expected — judge a threshold or scope change on a fresh scan.