Eloqua expression language

The Eloqua expression language (EEL) support for incorporating logic into decision making and filtering within Eloqua replaces the ExportFilter data transfer object that was present in Bulk 1.0. EEL simplifies and formalizes the syntax, providing a consistent way to interact with your data.

Operators

Comparison Operators

  • >
  • >=
  • <
  • <=
  • !=
  • =
  • ~ (This is the SQL Server LIKE operator. see: Like (Transact-SQL) on the Microsoft Developer Network documentation for appropriate syntax.)

Logical operators

  • AND
  • OR
  • NOT

Existence operators

EEL includes the EXISTS and STATUS operators as ways to filter based on a contacts’ presence or absence in a container, or on the status of associated containers. Unlike the comparison and logical operators, EXISTS and STATUS can only act on certain entities.

Note: You can only use one EXISTS and STATUS operator in a filter.

EXISTS

EXISTS is analogous to an IN operator. It determines if the object or entity exists within a container. The valid entities are: contact filters, contact segments, contact lists, and account Lists, as in the following examples:

EXISTS('{{ContactFilter[<id>]}}')
EXISTS('{{ContactSegment[<id>]}}')
EXISTS('{{ContactList[<id>]}}')
EXISTS('{{AccountList[<id>]}}')

The <id> being the entity's id (e.g. 12).

Note: EXISTS operators can only be used on exports of the same entity:
  • The ContactList, ContactFilter, or ContactSegment EXISTS operators can only be used in filters for contact exports.
  • The AccountList EXISTS operator can only be used in filters for account exports.

STATUS

STATUS describes the current status of a cloud connector, or AppCloud action, content, or decision service. STATUS does not currently support accessing email groups, campaigns, and so on.

For cloud connectors, use the following format:

STATUS('CloudConnectorStatus(<instanceid>)') = '<status>'

Where the <instanceid> is the instance’s ID, and <status> is either active or pending.

For AppCloud actions and decisions, the following format is correct:

STATUS('{{DecisionInstance(<instanceId>).Execution[<executionId>]}}') = '<status>'
STATUS('{{ActionInstance(<instanceId>).Execution[<executionId>]}}') = '<status>'

For AppCloud feeders the following format is correct:

STATUS('{{FeederInstance(<instanceId>)}}') = '<status>'

The <instanceId> being the GUID for the specific instance of the AppCloud service being used, and the <executionId> being the integer identifying a unique AppCloud service instance's execution. The <status> can be active, pending, complete, or errored.

Examples

Important: Wrap all operands in single quotes.

Comparison

Select contacts whose CreatedAt field is greater that 2018-12-31:

"filter" : "'{{Contact.CreatedAt}}' > '2018-12-31'"

Select contacts whose Account’s Company Name is not Eloqua:

"filter" : "'{{Contact.Account.Field(M_CompanyName)}}' != 'Eloqua'"

Logical

Important:

Supported filter formats with logical operators:

  • (A OR B) AND (C OR D)
  • A AND NOT B AND (C OR D)
  • A AND B AND (C OR D)
  • A AND (B OR C)

Note: Activity exports only support the A AND B AND C filter format.

Select contacts whose CreatedAt field is greater that 2018-12-31 and whose account's company name is not Eloqua:

"filter" : "'{{Contact.CreatedAt}}' > '2018-12-31' AND '{{Contact.Account.Field(M_CompanyName)}}' != 'Eloqua'"

Select contacts whose CreatedAt field is greater than 2018-12-31 and whose account's company name is not Eloqua and whose C_Country field is Canada or United States:

"filter": "'{{Contact.CreatedAt}}' > '2018-12-31' AND '{{Contact.Account.Field(M_CompanyName)}}' != 'Eloqua' AND ('{{Contact.Field(C_Country)}}' = 'CA' OR '{{Contact.Field(C_Country)}}' = 'US')"

Existence

EXISTS refers specifically to a container. The following filters contacts based on their presence in the ContactList with id 123:

"filter" : "EXISTS('{{ContactList[123]}}')"

STATUS. The following filter selects records for which the AppCloud action service instance ID is f82d50cd86a94fcab37e4ec9a98b0339, with an execution ID of 12345 and a status is pending:

"filter" : "STATUS('{{ActionInstance(f82d50cd86a94fcab37e4ec9a98b0339).Execution[12345]}}') = 'pending'"

Note: Filters have a 1000 character limit. Contact fields cannot be used in the filter for activity exports.

Grammar

grammar  Ebl;

options {
language = CSharp3;
output = AST;
backtrack = true;
}

@modifier{public}
@parser::namespace { Eloqua.Expression.Version1.Grammar }
@lexer::namespace { Eloqua.Expression.Version1.Grammar }

public expression
: WS!? orExpression WS!? EOF
;

orExpression
: andExpression (WS!? OR^ WS!? andExpression)*
;

andExpression
: notExpression (WS!? AND^ WS!? notExpression)*
;

notExpression
: (NOT WS!?)? atom
;

subExpression
: OPENPAREN! orExpression WS!? CLOSEPAREN!
;

atom
: comparison
| subExpression
;

comparison
: STRING WS!? GREATERTHAN WS!? STRING
| STRING WS!? GREATERTHANOREQUAL WS!? STRING
| STRING WS!? LESSTHAN WS!? STRING
| STRING WS!? LESSTHANOREQUAL WS!? STRING
| STRING WS!? NOTEQUAL WS!? STRING
| STRING WS!? EQUAL WS!? STRING
| STRING WS!? LIKE WS!? STRING
| EXISTS WS!? OPENPAREN! WS!? STRING WS!? CLOSEPAREN!
| STATUS WS!? OPENPAREN! WS!? STRING WS!? CLOSEPAREN! WS!? EQUAL! WS!? STRING
;

// Lexer tokens

// Comparison Operators
GREATERTHAN : '>' ;
GREATERTHANOREQUAL : '>=' ;
LESSTHAN : '<' ;
LESSTHANOREQUAL : '<=' ;
NOTEQUAL : '!=' ;
EQUAL : '=' ;
LIKE : '~' ;

// Existence Operators
EXISTS : E X I S T S ;
STATUS : S T A T U S ;

// Binary
AND : A N D;
OR : O R;

// Unary
NOT : N O T;

// Grouping
OPENPAREN : '(' ;
CLOSEPAREN : ')' ;

// Lexer rules
STRING : QUOTE ( ESC_SEQ | ~('\\'|'\'') )* QUOTE;
WS : (' '|'\t'|'\n'|'\r')+ ;

fragment
ESC_SEQ
: '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
| '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
;

fragment QUOTE : '\'' ;
fragment HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment A:('a'|'A');
fragment B:('b'|'B');
fragment C:('c'|'C');
fragment D:('d'|'D');
fragment E:('e'|'E');
fragment F:('f'|'F');
fragment G:('g'|'G');
fragment H:('h'|'H');
fragment I:('i'|'I');
fragment J:('j'|'J');
fragment K:('k'|'K');
fragment L:('l'|'L');
fragment M:('m'|'M');
fragment N:('n'|'N');
fragment O:('o'|'O');
fragment P:('p'|'P');
fragment Q:('q'|'Q');
fragment R:('r'|'R');
fragment S:('s'|'S');
fragment T:('t'|'T');
fragment U:('u'|'U');
fragment V:('v'|'V');
fragment W:('w'|'W');
fragment X:('x'|'X');
fragment Y:('y'|'Y');
fragment Z:('z'|'Z');