Skip to content

Configuring Dynamic Puller Filtering

Dynamic puller filtering allows a player system to send additional runtime data during a creative request so that Lucit can restrict which creatives are eligible to serve. This is a real-time filtering mechanism designed for players that capture contextual or live data and pass it back with each request.

This feature is especially useful when:

  • a player knows the current location, audience, category, or inventory context
  • the campaign needs to match on real-time data instead of static campaign rules
  • a client needs to generate custom tags for scheduling or third-party impression tracking
  • a platform or exchange wants to filter creatives based on live values such as venue, market, or content metadata

Examples include integrations like Place Exchange or Apparatix, where custom tags or runtime conditions can be used to determine whether a creative should be eligible at request time.

What this feature does

When enabled, a campaign can accept additional fields passed by the player in the request, and Lucit can evaluate those fields against the campaign's allowed creatives. The player sends a filter expression in the request, and Lucit applies it to the available creative set before returning the response.

If no creative matches the filter, the endpoint returns a 204 No Content response.

This is a good fit for real-time systems where the selection logic depends on current conditions instead of a precomputed export-only configuration.

Campaign setup

To enable this feature for a campaign:

  1. Open the campaign settings.
  2. Enable Supports Puller Filtering.
  3. Select the additional fields that the player may send from the allowed field list under Puller Filtering Allowed Fields.
  4. Save the campaign settings.
  5. Re-run the export so the XML export data includes the additional allowed fields that will be evaluated during pull requests.

Only fields explicitly allowed on the campaign can be used in dynamic filtering. If a field is not enabled for puller filtering, it cannot be used in the filter expression.

The following inventory item fields are available to select for puller filtering:

Field Label
title title
description description
new_used new_used
year year
make make
model model
sub_model sub_model
price price
item_class item_class
cached_tags cached_tags

Request format

Add a filter query parameter to the campaign pull request.

(Example endpoint - Your endpoint may differ depending on your integration with Lucit)

https://api.lucit.app/api/v1/campaigns/apx/v2/lch-4D5q/pull/html?api_token={APITOKEN}&n=Training|image-media&location_id=IM-07&filter=title:like(chevy)

In this example:

  • location_id=IM-07 is an additional runtime value being supplied by the player
  • filter=title:like(chevy) tells Lucit to return only creatives whose title contains the word chevy

The service then filters the campaign creatives down to only those items matching the provided expression.

No results case

If no creatives match the supplied filter, the request returns:

204 No Content

This behavior continues until the platform resolves the remaining edge cases associated with empty-match handling.

Example use cases

Dynamic puller filtering is useful for many different real-time scenarios:

  • show only creatives tagged for the current market or location
  • choose only creatives whose title or metadata matches the current ad context
  • filter by campaign-defined custom tags used for third-party tracking
  • support custom scheduling or exchange rules in a player that computes live signals
  • allow a player to pass real-time audience data and reduce creative selection to eligible items only

For example, a player might pass a custom tag such as exchange:apparel, region:north, or audience:homeowner and the campaign can restrict the eligible creatives based on those values.

Item Filter Expression Language

The filter syntax is a compact expression language used in the filter query parameter. It supports:

  • field comparisons
  • text matching
  • multi-value comparisons
  • boolean and empty-value checks
  • tag filtering
  • nested and and or logical groups

This is the language used to describe which creatives should be considered eligible for a request.

/filter?filter=status:eq(active)

Basic syntax

A filter condition uses this pattern:

field:operator(value)

Example:

status:eq(active)

Each part has a purpose:

Part Description
field The public name of the field being filtered
operator The comparison or matching operation
value One or more values passed to the operator

The exact fields and operators available depend on the endpoint and the campaign configuration.

Multiple values

Some operators accept more than one value. Use a comma-separated list:

status:in(active,pending,draft)

If a value contains commas, parentheses, or leading/trailing spaces, quote it:

city:in(Chicago,"Washington, D.C.")

Single and double quotes are both supported:

title:eq("Summer Sale")
title:eq('Summer Sale')

Logical groups

Filters can be grouped with and(...) and or(...).

AND

All conditions in the group must match:

and(status:eq(active),price:gte(100))

OR

At least one condition must match:

or(status:eq(active),status:eq(pending))

Groups may also be nested:

and(
  status:eq(active),
  or(
    city:eq(Chicago),
    city:eq(Minneapolis)
  )
)

When used in a URL, the expression can remain on one line:

/endpoint?filter=and(status:eq(active),or(city:eq(Chicago),city:eq(Minneapolis)))

Repeated filter parameters

An endpoint may also accept multiple filter[] parameters:

/endpoint?filter[]=status:eq(active)&filter[]=tags:any(sports,news)

These are implicitly combined with and:

and(
  status:eq(active),
  tags:any(sports,news)
)

Supported operators

Equality operators

eq

Matches when the field equals the supplied value.

status:eq(active)

neq

Matches when the field does not equal the supplied value.

status:neq(deleted)

in

Matches when the field equals any of the supplied values.

status:in(active,pending,draft)

not_in

Matches when the field does not equal any of the supplied values.

status:not_in(deleted,archived)

Text operators

like

Matches when the field contains or otherwise matches the supplied text according to the field's configured matching behavior.

title:like(summer)

like_any

Matches when the field contains or matches at least one of the supplied values.

title:like_any(summer,sale,clearance)

not_like

Matches when the field does not contain or match the supplied text.

title:not_like(discontinued)

Comparison operators

gt

Greater than.

price:gt(100)

gte

Greater than or equal to.

price:gte(100)

lt

Less than.

price:lt(500)

lte

Less than or equal to.

price:lte(500)

between

Between two values.

price:between(100,500)

Boolean and empty-value operators

These operators do not take a value argument; the parentheses are still required.

true

active:true()

false

active:false()

empty

description:empty()

not_empty

description:not_empty()

Tag operators

Tag operators are available only for fields configured as tag fields.

any

tags:any(sports,news)

all

tags:all(sports,featured)

none

tags:none(internal,archived)

Operator summary

Operator Arguments Description
eq 1 Equals
neq 1 Does not equal
in 1 or more Equals any supplied value
not_in 1 or more Does not equal any supplied value
like 1 Matches text
like_any 1 or more Matches any supplied text value
not_like 1 Does not match text
gt 1 Greater than
gte 1 Greater than or equal
lt 1 Less than
lte 1 Less than or equal
between 2 Between two values
true 0 Is true
false 0 Is false
empty 0 Is empty
not_empty 0 Is not empty
any 1 or more Contains any supplied tag
all 1 or more Contains all supplied tags
none 1 or more Contains none of the supplied tags

Examples

Match a single status

/endpoint?filter=status:eq(active)

Match one of several statuses

/endpoint?filter=status:in(active,pending,draft)

Match a tag

/endpoint?filter=tags:any(sports,news)

Match all tags

/endpoint?filter=tags:all(sports,featured)

Combine conditions with AND

/endpoint?filter=and(status:eq(active),price:between(100,500))

Use nested logical groups

/endpoint?filter=and(status:eq(active),or(city:eq(Chicago),city:eq(Minneapolis)),tags:none(archived))

URL encoding and escaping

Filter expressions should be URL encoded when included in a request. For readability, the documentation may show a filter like this:

/endpoint?filter=title:eq("Summer Sale")

The client may send it in encoded form instead:

/endpoint?filter=title%3Aeq%28%22Summer%20Sale%22%29

Most HTTP clients and query-string libraries handle this encoding automatically.

Quoted values support escape sequences including:

Escape Result
\" Double quote
\' Single quote
\\ Backslash
\n New line
\r Carriage return
\t Tab

Example:

title:eq("The \"Summer\" Campaign")

Validation and errors

A filter expression may be rejected when:

  • the field is not supported by the endpoint
  • the operator is not supported
  • the operator is not allowed for the selected field
  • the operator receives the wrong number of arguments
  • a value cannot be converted to the field's configured type
  • parentheses or quotes are not balanced
  • a logical group contains fewer than two expressions
  • the expression exceeds configured complexity limits

Invalid filter expressions should normally return a 422 Unprocessable Entity response with details about the validation issue.

Field-specific behavior

Although the filter language defines the available operators, each endpoint controls:

  • which fields can be filtered
  • the public name of each field
  • the data type of each field
  • which operators are permitted for each field
  • how like matching is performed
  • how empty values are interpreted
  • how values are converted before filtering

For example, an endpoint may allow:

price:gte(100)

but reject:

price:like(summer)

because price is configured as a numeric field rather than a text field.

Implementation notes

Dynamic puller filtering is a practical way to support player-side logic while keeping the campaign config and creative eligibility logic centralized.

It is especially useful when the player captures and passes live context during the request, such as:

  • tactical market conditions
  • venue or location signals
  • audience metadata
  • campaign tags
  • custom exchange or app metadata

This feature allows a player system to send those values as part of a creative request so Lucit can dynamically narrow the set of creatives that are eligible to run.

Summary

The basic workflow is simple:

  1. Enable Supports Puller Filtering on the campaign.
  2. Add any allowed fields to Puller Filtering Allowed Fields.
  3. Re-run the export so the fields are included in the data delivered to the player.
  4. Send filter= in the pull request with the appropriate expression.
  5. Return only matching creatives, or 204 No Content when nothing matches.

This gives player systems a flexible and real-time way to decide which creatives are eligible without needing to modify the campaign export itself at build time.