Learn the basics to start writing your first queries.

CQL uses a mix of natural language and technical notation — the latter borrowed mostly from JavaScript. This means you can choose between the natural style, the technical style, or a combination of both.

This flexibility makes CQL accessible to a wide range of users — from marketers and growth teams to developers and product managers.

The following table illustrates three equivalent expressions written in different styles:

Naturaluser's score is greater than 90
Technicaluser.score > 90
Mixeduser's score > 90

Throughout the documentation, we use natural notation to make the examples more accessible to non-technical readers, but you can use whatever style works best for your team.

Case sensitivity

CQL is a case-insensitive language, so the casing of words and variables does not affect the meaning of an expression. For example, user and USER refer to the same variable.

Note that this does not apply to string literals, which are case-sensitive. For example, "Croct" and "croct" are not equivalent.


You can add as many spaces, tabs, and line breaks as you like to make your queries more readable without affecting their meaning. CQL ignores any space characters unless they are part of a string literal.

Query structure

The structure of a query can be divided into two main parts: the variable declaration and the main expression.

// Variable declaration
let version = 1.0;
// Main expression
"CQL version " & version & " is here!"
Try in Playground

The most basic form of a CQL query is a single expression. However, you can also declare variables to store intermediate results and reuse them in the main expression. This is covered in the next section.

Variable declaration

The declaration block allows you to introduce new variables that can be used throughout the entire query. These variables are named values that can store the result of calculations or other expressions, enhancing the readability and maintainability of your query.

You can create multiple variable declaration blocks by separating them with semicolons. Each block begins with the let keyword, followed by a comma-separated list of variable definitions.

In a block, you assign a value to a variable by using the equals sign. The value can be any expression, including other variables or even a function.

// Variable declaration
let rocket = "🚀", speed = 28000; # km/h
let distance = speed * 24;
// Main expression
rocket & " travels " & distance & " km in one day"
Try in Playground

In the above example, the query declares three variables: rocket, speed, and distance. The first two are directly assigned a value. The third variable is set to the result of the expression speed * 24, which is then used in the main expression.

Main expression

The main expression is the part of the query that defines the logic to be evaluated.

This is where you can use the variables declared in the variable declaration blocks and any other built-in variables or functions available in the current context. Unlike the variable declaration blocks, the main expression does not end with a semicolon.


Comments are an essential part of any language, as they provide a way to add clarifications or notes without impacting semantics.

CQL supports both single-line and multi-line comments.

Single-line comments

Single-line comments start with // and continue until the end of the line.

// The first computer bug was discovered in 1947,
// and it was a real moth! 🦋

Alternatively, you can also use Python-style comments, which start with #:

# By the way, that's how the term "debugging" was born! 😅

Multi-line comments

For comments that span multiple lines, you can use multi-line comments enclosed in /* */, as shown below:

* 💡 Did you know?
* JavaScript was created by Brendan Eich in just 10 days in 1995.
* This explains a lot, doesn't it?

The multi-line comment syntax is also useful for temporarily disabling parts of your query without losing them:

/* user's status is "active" */ user's interests include "🎮"
Try in Playground

As you can see from the last example, you can also use the multi-line syntax for single-line comments. So you can use whichever comment type you prefer, as there is no practical difference between them.


Identifiers are the names assigned to variables, functions, or other user-defined elements in CQL. They are called identifiers because they provide a way to reference these elements within queries.

An identifier must begin with a letter or an underscore. After the first character, it can contain any combination of letters, digits, and underscores. Letters range from A to Z (case-insensitive), and digits range from 0 to 9.

Here are a few examples of valid identifiers:

  • name (simple and meaningful)
  • primaryButton (recommended for compound words)
  • _score (valid, but it is unclear what the underscore means)
  • color2 (valid, but it would be better as secondaryColor)
  • display_price (valid, but not recommended)

Invalid identifiers that do not meet the rules include:

  • 1section (starts with a number)
  • primary-button (contains a hyphen)
  • full name (contains a space)
  • .rating (starts with a special character)

It is a good practice to choose meaningful identifiers that convey the purpose of the variable or function they represent. This can make your queries more readable and easier to maintain.

Also, CQL is case-insensitive, meaning that it does not distinguish between uppercase and lowercase in variable names. But it is best to choose one way and stick with it. We recommend using displayPrice instead of display_price because it is more similar to natural language.

Reserved words

In CQL, certain words have special meanings and are reserved to prevent confusion or ambiguity. This means they cannot be utilized as identifiers for variables, properties, or any other elements in a query.

Croct's mascot neutral
How do I know if a word is reserved?

If you try to use a reserved word as an identifier, the query will fail to parse and return an error so you can fix it.

Note that CQL may reserve other words in the future. When using named variables and properties, it is advisable to avoid generic terms such as unless or when to prevent conflicts in future updates.