CommunityWriting & Editinggithub.com

croct-tech/agent-skills

>- Use when writing, reading, reviewing, or debugging Croct's Contextual Query Language (CQL): audience criteria, `croct.evaluate()` / `useEvaluation` / `<Personalization query>` / Next.js `cql` tag queries, Evaluation API `query` bodies (`/client/web/evaluate`, `/external/web/evaluate`), and dynamic content values (`"type": "dynamic"`, `"expression"`). Covers context variables (user, session, page, location, campaign, cart, device, browser, context, now/today), data types and conversions, accessors and selectors (`'s`, `property X of`, `[1st]`, `[*]`, `[...]`), tests (`is`, `matches`, `is like`, `contains either`, `is between`, `is defined`, `is returning`), quantifiers (`some ... satisfies`), macros, modifiers, event expressions (`user has viewed a page`, `user has abandoned a cart`, `user has completed goal`), audience estimation, and recipes. Triggers: "write an audience", "target mobile users in New York", "CQL syntax error", "audience never matches", "unavailable estimate".

What is agent-skills?

agent-skills is a Claude Code agent skill that >- Use when writing, reading, reviewing, or debugging Croct's Contextual Query Language (CQL): audience criteria, `croct.evaluate()` / `useEvaluation` / `<Personalization query>` / Next.js `cql` tag queries, Evaluation API `query` bodies (`/client/web/evaluate`, `/external/web/evaluate`), and dynamic content values (`"type": "dynamic"`, `"expression"`). Covers context variables (user, session, page, location, campaign, cart, device, browser, context, now/today), data types and conversions, accessors and selectors (`'s`, `property X of`, `[1st]`, `[*]`, `[...]`), tests (`is`, `matches`, `is like`, `contains either`, `is between`, `is defined`, `is returning`), quantifiers (`some ... satisfies`), macros, modifiers, event expressions (`user has viewed a page`, `user has abandoned a cart`, `user has completed goal`), audience estimation, and recipes. Triggers: "write an audience", "target mobile users in New York", "CQL syntax error", "audience never matches", "unavailable estimate".

Works with~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/croct-tech/agent-skills/tree/HEAD/skills/croct-cql

Installed? Explore more Writing & Editing skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Write and debug CQL

CQL is Croct's English-like query language. The same expression syntax powers audiences, real-time evaluation from SDKs and the HTTP API, and dynamic content values. Everything here is from docs.croct.com; when something is not covered, check the live docs (bottom of this file) instead of guessing.

Workflow

  1. Identify where the query runs: audience (must be boolean), evaluate/API (any JSON value, max 500 characters), or dynamic value (result must fit the attribute type, else default).
  2. Pick the data source: current context (page, cart, location, campaign, device), stored profile (user's ..., user's stats), session (session's ...), or history (user has ... event expressions, Scale plan).
  3. Check the data is collected: anything flagged integration required (profile attributes, cart, interests, goals, sign-in state) never matches unless the app sends it.
  4. Write it with the cheat sheet below; look up exact properties in context-and-data-types.md.
  5. Run the pitfalls checklist, then test with croct.evaluate() or the dashboard estimator.

Cheat sheet

// Natural, technical, and mixed styles are interchangeable
user's score is greater than 90
user.score > 90
user's score > 90
NeedSyntax
Propertyuser's address's city, user's stats' orders, property city of user's address, user.address.city
Odd key / indexpage.query['coupon-code'], list[0], (user's interests)[0]
Selectorscart.items[1st], [:first], [:last(2)], items[*].price, data[...].price
Literalsnull, true, 42, 3.14 (decimal), 3.14f, 51%, "str", 'raw', ~/re/i, [1, 2], ["k": "v"]
DatesNo literal: "2026-01-01" as date, "2026-01-01T12:00" as datetime; today + 1 day
Logicand or not (&& || !); and binds tighter than or
Compare== != > >= < <=; 1 < x < 3; is equal to X ignoring case
Literal shorthandX is "value", X is not 0 (right side must be a literal)
Stringsstarts with, ends with, matches "sub" / matches ~/re/i (case-sensitive), is like "sub" (case-insensitive)
Collectionscontains X, X is in [..], contains all of [..], contains either [..], contains neither [..]
Presenceis defined / is known, is empty
User/sessionuser is returning, user is anonymous, user is identified, session is starting
Datesis before, is after, is at "12:00", is between A and B [exclusive], today's weekday is "monday"
Quantifierssome x in C satisfies P, every, no, not every, at least 2 of any [distinct] x in C satisfies P
Macroscount of, sum of, average of, min of, max of, first of, last of, keys of, length of, number of days between A and B, this month
Modifiersas number, rounded [down], in title case, sorted descending, without duplicates, replacing "a" with "b", today at "12:00"
Fallbackuser's name or else "Anonymous" (??)
Conditional"A" if cond otherwise "B", cond ? "A" : "B"
Variableslet orders = user's stats' orders; orders >= 5
Events (Scale)user has <event> [with prop value] [at least N times] [in last 7 days]
Comments// line, # line, /* block */

Keywords and identifiers are case-insensitive; string literals are case-sensitive.

Context at a glance

VariableCommon properties
userid, firstName, email, age, company, jobTitle, interests, activities, stats' sessions, stats' orders, any custom attribute
sessionstart, duration, landingPage, referrer, stats' pageviews, stats' orders, audiences, experiences, experiments, custom attributes
page (web)title, url, path, query, anchor, referrer
locationcontinentCode, countryCode, countryName, stateCode/regionCode (alias of state's code), stateName, cityName, timeZone, tags
device / browsercategory (desktop, tablet, mobile, bot, ...), vendor, name, os; browser's name, type
campaignname, source, medium, content, term (UTM)
cartstage (browsing, shopping, checkout), items, total, subtotal, coupon, discount
contexttimeZone, attributes passed at evaluation
now, today, yesterday, tomorrowweekday, day, month, year, hour...

Most useful patterns

user is returning
user is not returning
session is starting
device's category is "mobile"
device's category is not "bot"
location's countryCode is "US"
location's state's code is in ["NY", "CA"]
location's cityName is "New York" and today's weekday is "monday"
campaign's source is "google" and campaign's medium is "cpc"
campaign's name matches "sale"
page's path is in ["/pricing", "/plans"]
page's query's newsletter is "daily-news"
page.query['coupon-code'] is defined
session's referrer matches "google"
session's landingPage starts with "https://example.com/promo"
session's duration > 5 minutes and session's stats' orders is 0
user's interests contains either ["marketing", "sales"]
user's age is between 18 and 30
user's stats' orders is 0
user's plan is "premium"
cart's stage is "checkout" and cart's total is greater than 100
some item in cart's items satisfies item's brand is "Apple"
(no item in cart's items satisfies item's name is like "smartphone") and user is returning
user has abandoned a cart at least 2 times
user has viewed a product with category "Shoes" in last 7 days
user has completed goal "demo-requested" last session
user's firstName or else "there"

More by use case (campaign, location, technology, session, profile, cart, orders, value queries): references/recipes.md.

Evaluate from code

import croct from '@croct/plug';

const isReturning = await croct.evaluate<boolean>('user is returning').catch(() => false);
const inList = await croct.evaluate<boolean>(
  "context's countries include location's countryName",
  {attributes: {countries: ['United States', 'Canada']}}, // read as `context's countries`
);

Next.js server: await evaluate(query) or await cql`user's persona is in ${roles}` from @croct/plug-next/server. React: useEvaluation(query). HTTP: POST https://api.croct.io/client/web/evaluate with {"query": "..."}. Details, attribute limits, dynamic values, and estimation: references/evaluation.md.

Pitfalls and debugging

SymptomLikely causeFix
Syntax error on x is yis shorthand needs a literal on the rightx is equal to y or x == y
Syntax error on location city is "Berlin"Missing accessor: bare words between a variable and its propertylocation's cityName, property cityName of location, or location.cityName
Error comparing "1" > 0 or session's start > "2026-01-01"Relational operators never convert typesCast: "1" as number > 0, ... > "2026-01-01" as datetime, or use is after
Location/code never matchesWrong case: codes are upper case ("US", "NA", "CA") and strings are case-sensitiveUse upper case, is like, is equal to ... ignoring case, or ~/.../i
matches "Sale" misses "sale"matches, starts with, ends with are case-sensitiveis like "sale" or matches ~/sale/i
Quantifier swallows following conditionQuantifier predicate extends to the endParenthesize the whole quantifier
a or b and c behaves oddlyand binds tighter than orAdd parentheses
Conditional result multiplied wronglyConditionals are greedy(A if c otherwise B) * price
Profile/cart/interest condition never trueIntegration-required data not sentTrack the event or set the attribute (see the croct-track-events skill)
Both X is greater than 30 and X is not greater than 30 falseUndefined value: boolean error tolerance yields falseUse X is defined and ..., or X or else 0
user is identified always falseSign-in/up/out events not trackedTrack them; otherwise users are always anonymous
cart.items[2nd], first of, average of, min of errorsMissing element or empty collectionAppend or else null / or else 0
contains none of [] vs contains neither []Empty right side: none false, neither trueUse contains neither for "no overlap"
Error mixing 's with bracketsOwnership/possessive plus brackets need parentheses(cart's items)[1st] or dot notation cart.items[*]
Event expressions unavailableThey are a Scale plan featureUse profile/session stats where possible (user's stats' orders)
"Unavailable estimate"Uses page, current context, or now/today/yesterdayExpected; audience still works at runtime
Range error.. ranges max 30 itemsNarrow the range
Variable/parameter name errorVariables cannot be redefined; names must be identifiersRename; avoid built-ins (user, page) and generic words

Do:

  • Prefer explicit is equal to, is greater than in audiences shared with non-developers; use technical style when it reads better.
  • Guard optional data with is defined or or else.
  • Put cheap conditions first in and chains (short-circuiting skips the rest).
  • Use contains either / contains neither rather than negating contains all / contains none.

Don't:

  • Don't invent tests, variables, or event phrasings. Examples such as user is new or user has made purchase appear in docs prose but are not documented constructs; use user is not returning and user's stats' orders is not 0 (or user has placed an order).
  • Don't compare location's countryName with a code; use countryCode for "US".
  • Don't rely on implicit date conversion in arithmetic: "2021-01-01" as date + 1 day.

References

FileRead when
references/syntax.mdLexical rules, let, functions, literals, accessors and selectors, precedence table, conditionals, durations
references/context-and-data-types.mdEvery variable and property, availability flags, enums (device category, cart stage, continent, location tags), conversions
references/expressions.mdAll tests, operators, error tolerance, quantifiers, macros, modifiers
references/events.mdEvent expressions, criteria operators, count quantifiers, time windows, tracking requirements
references/evaluation.mdSDK evaluate / cql / hooks, Evaluation API, context attributes, dynamic values, audience estimation
references/recipes.mdReady-to-use audiences and value queries by use case

Related skills: croct-integrate-sdk (SDK setup), croct-track-events (sending the events and attributes that queries read), croct-use-api (HTTP APIs), croct-model-content (dynamic values in content definitions), croct-personalize-and-test (experiences and experiments that use audiences), croct-use-croct (concepts and orientation).

Live docs

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

croct-tech/agent-skills

>- Use when connecting Croct to a third-party platform or migrating to Croct from another personalization or experimentation tool. Covers Storyblok (Optimize by Croct app, @croct/plug-storyblok, Storyblok withCroct, resolveContent, croct/plug-storyblok, CroctStoriesApi), Sanity and Strapi (slot fallback, dynamic zones, metadata.contentSource), Shopify Hydrogen storefront events, Shopify custom pixel (croctPixel, PUBLIC_CROCT_SHOPIFY_PIXEL, checkout and order tracking), VTEX, Google Tag Manager data layer, Microsoft Clarity tags, HubSpot forms (hbspt.forms.create, hs-form-event), firmographic providers 6sense, Demandbase, Clearbit Reveal, and ZoomInfo WebSights (firmographics attributes, account-based audiences in CQL), and migrations from Mutiny and Ninetailed (Experience component, Contentful sunset). Triggers include cdn.croct.io/plug-integration scripts, "personalize Storyblok blocks", "track Shopify checkout", "send VTEX events", "ABM personalization", "replace Mutiny".

croct-tech/agent-skills

>- Use when installing or using a Croct SDK in application code: rendering slot content, evaluating CQL queries, server or client fetching, prerendering, identifying users, app ID / API key env vars, testing, or debugging. Covers JavaScript (`@croct/plug`, `croct.fetch`, `croct.evaluate`), React (`@croct/plug-react`, `<CroctProvider>`, `useContent`, `<Slot>`, `useEvaluation`, `useCroct`), Next.js (`@croct/plug-next`, `fetchContent`, `cql`, middleware/proxy, `NEXT_PUBLIC_CROCT_APP_ID`, `CROCT_API_KEY`), Vue (`@croct/plug-vue`), Nuxt (`@croct/plug-nuxt`), Shopify Hydrogen (`@croct/plug-hydrogen`), PHP (`croct/plug-php`), Laravel, Symfony, and Drupal. Triggers: slot IDs like `home-hero@1`, `SlotContent`, "Croct is not plugged in", "initial content is required for server-side rendering", "Did you forget to configure Croct's middleware?", CORS errors.

croct-tech/agent-skills

>- Use when designing or changing Croct content models: regular vs union components, what becomes a component, slot, structure, or primitive attribute; writing component schema JSON (`structure`, `union`, `reference`, `text`, `number`, `boolean`, `list`, `@croct/file`, `@croct/richText` rich text, `format`, `choices`, `optional`, `private`, `position`); writing content definition JSON (`static`/`dynamic` values, `nullable`, `default`, `{{placeholder}}` paths); slot default, localized, experience, experiment, or content group content; schema limit errors (30 attributes, 6 nesting levels, 10 union members, complexity score 50); component versioning and breaking changes (`home-hero@2`); refactoring (duplicate and modify, duplicate and replace, flatten and merge); Markdown in text attributes with `@croct/md-lite`. Phrasings: "model content for a hero", "add an attribute to the banner component", "support variations", "component is too complex", "localize the hero", "translations", `preferredLocale`.

croct-tech/agent-skills

>- Use when planning or implementing personalization or A/B testing with Croct: creating an experience (audience, slots, content, priority, scheduling, drafts), adding an experiment (A/B/n, primary goal ID, traffic allocation, variants, cross-device consistency), wiring the code it needs (slots, `croct.track('goalCompleted', {goalId})`, `orderPlaced`, `leadGenerated`, `userSignedUp`), server-side feature-flag experiments, redirect experiments, personalization recipes (UTM campaigns, ABM, search terms, location, free shipping, interests, blog readers, leads, customers, organic intent, HubSpot forms), or reading the experience, experiment, application, or workspace dashboards (probability to be best, potential loss, "Experiment in progress", "Recommended winner", "No clear winner", "Track your goal"). Phrasings: "personalize the hero for LinkedIn visitors", "A/B test this CTA", "which variant won?", "why does my experiment show no conversions?".

Related Skills