Browse the help center

Custom Parameter targeting reference

Every Custom Parameter operator with a worked example, how the Value list and the request value are split, has all of, the absent-parameter matrix, the Expression kind, the Cookie Value dimension with and / or between cookies, and the REST API.

Reference network manager publisher advertiser Account → entity → Targeting / Pre-targeting → Custom Parameter

The tables behind Target on custom parameters passed in the ad tag. Every comparison is case-sensitive on the value and case-insensitive on the key name, and values are compared as strings unless the operator is numeric.

The editor

ControlShown forWhat it does
TypealwaysThe rule kind: Expression, Value, One of or Substring. Changing it clears the other fields.
ParameterValue, One of, SubstringThe key to read off the request, with any cp. / cp_ prefix already stripped. Picked from the registered parameters (name · label) or typed after Other parameter…; a plain text box when nothing is registered. It has an ⓘ only for a list parameter on a Value or One of rule: Arrives as a list split on ”,” on One of, Arrives as a list: use One of to match one item on Value.
OperatorValue, One of, SubstringThe comparison; the choices depend on the kind, and the label has no ⓘ. has all of appears only for a list parameter and is cleared when the parameter changes to a plain one.
ValueValue, One of, SubstringOne value for Value; a comma-separated list for One of and Substring. The ⓘ beside it says what the picked operator matches, how to separate values and, on a list parameter, previews a match in that parameter’s own separator. The placeholder shows the shape (sport, news, travel). When the parameter has a registered list of values, One of picks from it and a Value equals / not equals rule picks one.
ExpressionExpressionA single boolean expression; the ⓘ recaps the syntax.
Include / ExcludealwaysSaves the drafted rule as a whitelist or blacklist entry; disabled until the editor is complete.

What each kind matches

KindOperatorMatches whenWorked example
ValueequalsThe value is exactly equalsection equals sport matches cp.section=sport, not Sport
Valuenot equalsThe value is anything else, including absentsection not equals sport matches cp.section=news
Value> ≥ < ≤Both sides parse as numbers (dot decimals, 1e3 accepted) and the comparison holdsage ≥ 18 matches cp.age=18 and cp.age=18.5, not cp.age=17 or a missing age
One ofis one ofThe value exactly equals one entry in the listsection is one of sport, news, weather matches cp.section=news
One ofis not one ofThe value equals no entry, including absentthe same list rejects news, accepts travel
One ofhas all ofEvery entry in the list is an item of the value; other items may be there too. List parameters onlysegments has all of 1, 3 matches cp.segments=1,2,3,4,5 and 1,2,3, not 1,4,5
SubstringcontainsThe value contains at least one entry as a substringpath contains /sport/, /live/ matches cp.path=/2026/sport/final
Substringnot containsThe value contains no entry, including absentthe same list rejects that path, accepts /news/uk
Expression—The expression evaluates to trueThe Expression kind

The Value kind’s rule value is trimmed when loaded and has no length limit. The Value field also expands $name: $otherparam compares one request parameter against another.

How the Value list is split

One of and Substring take a list in one Value field. This is the rule’s own list; whether the request value is split too is a setting of the parameter — see When the request sends several values.

  • The separator is a comma only. A semicolon becomes part of the value. A line break is not a separator either: the box is a single line, so a pasted column arrives with its lines run together — 345, 456 on two lines do not become two values. Put commas between them first.
  • The whole list is URL-decoded before it is split, then each entry is trimmed and empties are dropped. Duplicates collapse — the entries are held as a set. So a typed + reads as a space and %2B as +; write a literal % as %25. A typed list holding a lone % (50%, a+b) fails to decode as a whole, and its + then stays a plus.
  • One of: a backslash makes the next character literal — \, is a comma inside the value, \\ a backslash, and a backslash before any other character is dropped.
  • Substring: splits on commas not preceded by a backslash and keeps the backslash, so a part written a\,b matches the literal text a\,b. A Substring part can therefore never hold a comma; %2C does not help, because the list is decoded before it is split.
  • Values picked from a parameter’s registered list are written in this form for you — 18+, 50% and a\b are stored as 18%2B, 50%25 and a\\b — so each pick counts whole, commas and spaces included, and the rule’s summary shows them as picked.
  • Substring URL-decodes the incoming request value too, so /sport/ matches a request carrying %2Fsport%2F and vice versa. Value and One of compare the raw string.

When the request sends several values

A tag can pack several values into one parameter — cp.genre=rock,pop, or a CTV stitcher’s contentGenre=Comedy,Drama. Out of the box a One of rule compares that value whole, so genre is one of pop does not match rock,pop. Register the parameter under Admin → Custom parameters and switch on The request can carry several values, choosing its separator — comma, pipe, semicolon or space. From then on every One of rule on that parameter reads the request value item by item:

RuleRequest cp.genre=rock, pop,,Jazz (items rock, pop, Jazz)
Include · is one of popmatches — any item in the list is enough
Include · is one of jazzno match — values stay case-sensitive, Jazz ≠ jazz
Include · is not one of popno match — no item may be in the list
Include · has all of rock, jazzno match — rock is an item, jazz is not (Jazz ≠ jazz)
Include · has all of rock, popmatches — every value is an item; Jazz being there too does not matter
Exclude · is one of popfires — the request is turned away when any item matches
any rule, parameter absent or blankno items: is one of and has all of never match, is not one of always does
  • Items are trimmed and empty ones ignored: rock,,pop and rock , pop both read as rock, pop.
  • has all of asks for every value at once: segments has all of 1, 3 matches 1,2,3,4,5 and 1,2,3, not 1,4,5 (3 is missing). Order does not matter, a repeated item counts once, other items may be there. On a parameter split on | the request reads 1|2|3|4|5 and the editor’s ⓘ shows the example in that separator. It is offered only on a list parameter — read whole it could only mean “equals” — and the server refuses it elsewhere. There is no negated form: add the same rule with Exclude.
  • A value without the separator is a one-item list, so it matches exactly as before the parameter was registered. Only values that contain the separator change.
  • The setting belongs to the parameter, not to the rule: every One of rule on it, on any entity, at any level, splits the same way. The ⓘ beside Parameter says so, the ⓘ beside Value previews a match, and the saved chip ends in · list.
  • Only One of splits. Value, Substring and Expression rules read the whole value — the editor points a Value rule on a list parameter at One of — and so does the $$CUSTOM_PARAM()$$ macro. In reports, the Advanced report’s custom-parameter filter matches an item the same way, while grouping by Custom parameter shows the whole value.
  • Ad serving keeps the registered parameters in memory and reloads them every minute.
  • A One of value that itself holds the separator (rock\,pop) can never equal one item, so that rule never matches; the editor warns as you type it and the parameter’s admin page lists such rules under Used by.
  • The request value is URL-decoded once, by the server, before it is split: rock%2Cpop arrives as rock,pop and splits; a double-encoded rock%252Cpop arrives as rock%2Cpop and does not.

Several rules: any of or all of

Within the dimension, Include rules are combined with or — one matching rule is enough — while the first Exclude rule that matches rejects the request. Rules on one parameter are always alternatives, because a request carries one value for it: tier equals gold and tier equals silver mean “tier is gold or silver”. Rules on different parameters, every rule on a list parameter (including a single has all of), and every Expression are groups of their own.

The connector between groups is the list’s mode: or ▾ by default, and ▾ when every group must match — ( tier=gold or tier=silver ) and genre is one of [pop]. A list with one group shows no connector. On a list parameter two One of rules joined by and need both items in the request; one has all of rule does the same inside one rule. Click the connector on the Targeting card, or call POST …/targeting/match-mode with type=CUSTOM (And / or between groups). A rule added later joins its list’s mode; a copied campaign or creative and a target template keep it. The classic UI shows the mode in the group header and has no control.

When the request does not carry the parameter

A missing parameter resolves to the empty string and the comparison runs normally, so the negative operators match. (Epom can configure a server-side default value for a parameter — none is set out of the box; where one is, an absent or blank parameter takes it.)

Kind and operatorResult when absentAs an Include ruleAs an Exclude rule
Value equalsno matchrequest is rejectedrule does not fire; request passes
Value > ≥ < ≤no match (empty is not numeric)request is rejectedrule does not fire; request passes
One of is one of / has all ofno matchrequest is rejectedrule does not fire; request passes
Substring containsno matchrequest is rejectedrule does not fire; request passes
Value not equalsmatchrequest passesrequest is rejected
One of is not one ofmatchrequest passesrequest is rejected
Substring not containsmatchrequest passesrequest is rejected

An Include rule with a positive operator added before the tag sends the parameter takes the entity off air on that placement; an Exclude rule with a negative operator fires on every request that omits it. “Exclude sport” is Exclude + equals, not Include + not equals.

The Expression kind

Expression is the only kind that can combine several parameters or use || and &&. It is a JavaScript expression, evaluated server-side, in which each parameter is written $key.

The substituted value is quoted for you. $section is replaced by 'sport' — quotes included, JavaScript-escaped, '' when missing — so compare against a quoted literal or a bare number and never wrap the $key yourself:

$section == 'sport' && $age >= 18

For cp.section=sport&cp.age=21 that becomes 'sport' == 'sport' && '21' >= 18, which is true — JavaScript coerces the quoted number for >=. '$section' == 'sport' produces ''sport'' == 'sport', a syntax error.

String and array methods and regular expressions work — though for “any of these values” a One of rule on a list parameter does the same without running a script on every request:

$cat.split(",").indexOf("a") >= 0
($a + $b) > 0
($p1 == 1 || $p1 == 'a') && ($p2 >= 12 && $p2 <= 22)
/^en/i.test($lang)
  • A $key name may contain letters, digits, underscores and $. Longer names are substituted first, so $aa is not corrupted by a rule that also mentions $a. Key names ignore case.
  • $CLIENT_USER_AGENT is always available: the request’s full User-Agent string, injected by the ad server. It is the supported way to test something the dimension list has no picker for: /Android (.*?);/i.exec($CLIENT_USER_AGENT)[1] >= '2.3'.
  • === and !== are strict: against a quoted literal they behave like ==, but $age === 18 compares a string with a number and never matches. The placeholder reads $parameter1 === 'value'; keep === for quoted literals and use == for numbers.
  • An invalid expression is rejected when you add the rule, with “Please enter valid expression (Sample: ($p1==1 || $p1==‘a’) && ($p2>=12 && $p2<=22))”. The check is server-side: Include enables as soon as the box is non-empty.
  • An unquoted bare word is an identifier, not a literal: $section == sport throws, which is read as “could not evaluate” and rejects the request on an Include rule. An expression that returns a non-boolean ($section alone) passes the save-time check and never matches.
  • Each evaluation has a statement budget, generous for a boolean expression; a script that spends it (a loop that does not end) is aborted and read as “could not evaluate”.
  • Results are cached for an hour, keyed on the fully substituted text. Harmless for a pure function of the parameters; stale for anything else, such as new Date(). Use the Time Range or Day and Time dimensions for wall-clock logic.

Target the show a stitcher describes

A CTV stitcher that calls a VAST tag set up with an upstream macro preset fills four content parameters on the request. They are targetable like any parameter, with no cp. prefix:

ParameterCarriesExample rule
contentGenrethe show’s genre, as the stitcher names itOne of — is one of — Sports, News, as Include
contentRatingits age rating, such as TV-PGOne of — is one of — TV-MA, TV-14, as Exclude
contentLivestream1 for a live stream, 0 on demandValue — equals — 1, as Include
contentLanguagethe show’s languageOne of — is one of — en, es, as Include

They are read the way buyers receive them in content.*: a value the stitcher left as an unexpanded macro ({{CONTENT_GENRE}}, [player_params.contentGenre]) counts as not sent, values are trimmed, and a live flag sent as true / false reads as 1 / 0. Genre and rating are free text, so match the spellings your stitcher sends — a troubleshooting task on the placement shows the full request URL. A request without the value, or with the macro unfilled, behaves exactly like one that omits the parameter (absent-parameter matrix).

Cookie Value is a separate dimension with two fields, Name and Value, both required and trimmed. It reads a value that persists on the visitor’s browser rather than one on the current request.

It does not read any first-party cookie your own script writes. It reads only cookies Epom itself set, whose names carry Epom’s third-party cookie prefix — eas_3p_ by default. The Name you type is the part after that prefix, so a cookie named eas_3p_segment is matched by a rule on segment. Names compare exactly; values compare whole, ignoring case (Cart-Abandoner matches cart-abandoner).

Those cookies are written by Epom’s cookie-setting endpoints — /multi-cookie.gif, /multi-cookie.js and /multi-cookie.html — which turn each query parameter into a cookie:

<img src="https://<ad-serving-domain>/multi-cookie.gif?segment=cart-abandoner|30d"
     width="1" height="1" alt="">

The value takes the form value|lifetime|format:

PartMeaning
valueWhat the rule’s Value field is matched against.
lifetime30d days, 12h hours, 45m minutes, 30s seconds, 1y years. A bare number means days. Omitted, the cookie lasts 365 days.
formatPLAIN (the default) or BASE64.
Custom ParameterCookie Value
Where the value livesthe current ad requesta cookie Epom set on the browser
Who writes itthe publisher’s tag or the placement defaultsEpom’s /multi-cookie.* endpoints
Lifetimethat one requestthe cookie’s, 365 days by default
Rule kindsfourone — name plus exact value
Value comparisoncase-sensitivecase-insensitive

Everything else matches Custom Parameter: same card, same Include/Exclude, applied immediately. A Cookie Value rule whose Name is empty is skipped at serving time — the editor will not create one, but a rule imported through the API can be in that state and then silently does nothing.

Several cookies: any of or all of

The Include rules of one entity form one list and its Exclude rules another. Inside a list, the values given for one cookie name are always alternatives: a browser keeps one value per name, so tier = gold and tier = silver mean “tier is gold or silver”. The connector between different cookie names is the list’s mode — or ▾ by default, and ▾ when every cookie is needed (And / or between groups).

Listor (default)and
Includethe visitor needs one of the listed values of any one cookiethe visitor needs every listed cookie, each with one of its listed values
Excludeone listed value of any cookie keeps the visitor outthe visitor is kept out only when every listed cookie has one of its listed values

An Include list of tier = gold, tier = silver and region = eu reads ( tier=gold or tier=silver ) or ▾ region=eu. Click the connector and it reads ( tier=gold or tier=silver ) and ▾ region=eu: a visitor with tier=silver and region=eu passes, a visitor with only tier=gold does not, and bronze + eu fails. A list that names one cookie only (test = 1, test = 2) has a single group and no connector — it means “test is 1 or 2” either way. A cookie added later joins its list the way the list combines now, so a fourth cookie added to an and list is required too. A copied campaign or creative and a target template keep each list’s mode. The classic UI has no control; it reads the list out in the group header, e.g. · (tier = gold or silver) and region = eu. A longer list shows its first three values and counts the rest (· segment A or segment B or segment C +47 more); hover the header for the whole expression.

A visitor who saw pricing and booked a demo and started sign-up, in any order, but did not buy:

  1. Fire one pixel per step, each under its own cookie name:

    <img src="https://<ad-serving-domain>/multi-cookie.gif?visited_pricing=1|30d" width="1" height="1" alt="">
    <img src="https://<ad-serving-domain>/multi-cookie.gif?visited_demo=1|30d" width="1" height="1" alt="">
    <img src="https://<ad-serving-domain>/multi-cookie.gif?visited_signup=1|30d" width="1" height="1" alt="">
    <img src="https://<ad-serving-domain>/multi-cookie.gif?purchased=1|90d" width="1" height="1" alt="">
  2. Add three Cookie Value rules with Include — visited_pricing = 1, visited_demo = 1, visited_signup = 1 — and click the or ▾ between them so it reads and.

  3. Add purchased = 1 with Exclude.

The list asks which cookies the visitor has, not the order they were set in.

  • To require several steps, give each step its own cookie name. step=pricing followed by step=demo overwrites the first, and step = pricing plus step = demo in one list means “step is pricing or demo” — never both.
  • Every cookie of an and list must still be alive when the visitor reaches the last step. A |1d cookie on the first step of a week-long funnel quietly drops the visitor.
  • and does not widen reach. A Cookie Value rule matches only when the browser sends the ad server’s cookies with the ad request — not on Safari or any iPhone browser, not on Firefox across sites, not in private windows, apps or connected TV — and those visitors fail an and list exactly as they fail a single cookie. With detailed targeting logging on for the ad servers, a troubleshooting task records which cookie a rejected request was missing, or that it carried no targeting cookies at all.
  • A value both included and excluded is flagged as a contradiction while the Exclude list keeps out a visitor with that value alone — when it reads or, or holds one group only. An and Exclude list of two groups or more keeps out only a visitor matching all of them, so the shared value is no contradiction there; the card flags it only when the Include list asks for every one of those groups, and only for values the Exclude list also names, because then nobody gets through. The same holds across levels: a campaign’s and Exclude list does not flag a creative that includes one of its cookies. Switching an Exclude list back to or checks again, and the switch (on the card or over the API) answers with the warning when a pair turns into a contradiction.

API

{entity} is advertiser, campaign, banner, site, zone or placement.

Create a Custom Parameter rule — POST /rest-api/{entity}/{id}/targeting/custom/create.do with rule (INCLUDE / EXCLUDE), customValue, and for the non-expression kinds customType, operation and parameter. Enum values are the names: customType is EXPRESSION, VALUE, ONE_OF or SUBSTRING; operation is EQUALS, NOT_EQUALS, GREATER, GREATER_OR_EQUALS, LESS, LESS_OR_EQUALS, IN, NOT_IN, ALL (has all of), CONTAINS or NOT_CONTAINS (note the plural EQUALS). A name outside that list is refused with a 400 that names the parameter and lists the accepted values; a missing operation or parameter, an operation the kind does not support (CONTAINS on VALUE), and ALL on a parameter that is not registered as a list are 400s too. An invalid expression is a 400 whose message starts Please enter valid customValue (Sample: …).

Switch a list between or and and — POST /rest-api/{entity}/{id}/targeting/match-mode with type (CUSTOM, COOKIE_VALUE, DMP or API_JSON_FIELD), rule (INCLUDE / EXCLUDE) and matchMode (ANY / ALL). The response carries the type, the rule, the saved matchMode, how many rules changed and, when a value is now both included and excluded, a warning. A missing or unknown type, rule or matchMode, a type without a mode, or an empty list is a 400; 403 and 404 as usual. A rule added later joins its list’s mode, and every rule of these types reads back with its matchMode and matchGroup (the parameter or cookie name).

Cookie Value — POST /rest-api/{entity}/{id}/targeting/cookie-value/create adds a cookie rule, which joins its list’s mode.

Permissions

WhatDemand side (advertiser, campaign, creative)Supply side (site, zone, placement)
See and use Custom ParameterCustom under the role’s Targeting permissions + Manage Demand TargetingCustom under Pre-targeting permissions + Manage Supply Pre-targeting
See and use Cookie ValueCookie Value under Targeting permissionsCookie Value under Pre-targeting permissions
Switch or / andthe same, plus the right to manage the type; a reader without it sees plain and / orthe same
Shared entityCan View shows the rules; adding, removing or switching needs Can Edit or Is Owner—

Related pages

Please disable Adblock
Are you using adblock? Disable it and reload the page to proceed to the destination page.

A registration has already been submitted from this page. Please try again in 10 minutes.