> log #09 — Clay formulas, decoded.
Where a marketer again pretends to be a dev. My Github bio: "sometimes i make pull requests"
Sometimes marketing tools feel like a black box. Clay is different — it lets you peek under the hood. And when you do, you find out the “magic” is just a sprinkle of JavaScript and regex.
But first, a quick cheatsheet of the building blocks you’ll see in every Clay formula:
Phase 0: What am I even looking at?
{{Website}} → Clay variable.
Double curly braces pull in a field from your table.
Example: {{Title}} = the person’s job title column.
|| "" → Fallback operator.
Read as “OR.”
Means: if the field is empty/null, use a blank string instead.
.toLowerCase() → String method.
The . means “do this action to the thing before it.”
Example: "HELLO".toLowerCase() → hello.
.replace(...) → Another string method.
Find something in the text → replace it with something else.
.split("/") → Break the text into pieces at /.
split makes an array: "a/b/c".split("/") → ["a","b","c"].
[0] grabs the first piece.
/pattern/i → Regex literal.
A way to define text-matching rules.
The i at the end = ignore case.
? ... : ... → Ternary operator.
Shorthand if/else.
Example: isSunny ? "Go outside" : "Stay in"
👉 Once you know these symbols, Clay formulas stop looking like alien code and start feeling like Lego blocks.
Phase I: Cleaning up websites (the gateway drug)
My CSV had messy website data like:
https://www.example.com/page
http://example.org
www.testsite.net
But all I really wanted was the core domain:
example.com
example.org
testsite.net
Here’s the formula that fixed it:
({{Website}}||"")
.toLowerCase()
.replace(/^https?:\/\/(www\.)?/, "")
.split("/")[0]
How it works:
{{Website}}||"" → Grab the Website field, or use "" if it’s blank.
.toLowerCase() → Force everything lowercase (so EXAMPLE.COM ≠ Example.com).
.replace(/^https?:\/\/(www\.)?/, "") → Strip off http://, https://, and www..
.split("/")[0] → Chop at the first /, keep only the domain.
👉 End result: clean, consistent domains you can use for enrichment or joining across datasets.
Phase II: Regex for matching text (job titles example)
Once you’re comfy with string cleaning, regex lets you spot patterns in text.
Formula:
/ceo|co[-\s]?founder|cro|chief revenue officer/i.test({{Title}}||"")
? "C-suite"
: "VP"
Breakdown:
/.../i = regex pattern, case-insensitive.
.test(...) = check if the title matches (true/false).
? "C-suite" : "VP" = return C-suite if true, else VP.
👉 In plain English: “If the job title looks like C-suite, label it C-suite. Otherwise, label it VP.”
Phase III: Clay’s “Describe your formula” (and prompt) generator — how to really use it
Clay lets you write plain English and it will turn that into a working snippet. You’ll see this helper in multiple places:
Column → Formula (create a computed column)
Enrich step → Transform (massage data inside a workflow)
Write with AI / Categorize with AI (describe logic or a prompt)
Map fields (some mapping dialogs support “Describe the formula” too)
The UI labels vary a bit, but the pattern is the same: there’s a text box that says something like “Describe your formula (or prompt)” and a Generate button. You type what you want in plain English; Clay converts it to JavaScript and/or regex.
The /field syntax (super important)
When you’re describing your formula (not when you’re writing raw JS), you can reference columns by using a leading slash:
/email → pulls the column named “Email”
/company → “Company”
/title → “Title”
If your column has spaces or punctuation, keep typing after the slash and select the column from the picker Clay shows you.
This is the easiest way to “grab” the data you want in a generator prompt without remembering {{curly}} syntax. The generator will convert your /field references into the proper {{Field}} placeholders.
TL;DR: In Describe mode, use /field. In raw formula mode, use {{Field}}.
Your example, end to end
Plain-English description (what you type):
look at the two job title columns /title - people - results and /title - peoples and output C-Suite if their title is CRO, Chief Revenue Officer, CEO, Founder or Co-Founder. output VP for every other job title.
Click → Generate formula
Result (what Clay produced):
/cro|chief revenue officer|ceo|founder|co-founder/i.test(({{Title - People - Results}}||"")?.toLowerCase() + " " + ({{Title - Peoples}}||"")?.toLowerCase()) ? "C-Suite" : "VP"
What happened:
Your /title - people - results and /title - peoples references got converted to {{Title - People - Results}} and {{Title - Peoples}}
Clay lowercased both titles, concatenated them, then used a regex + .test() to return true/false
The i flag on the regex makes it case-insensitive
The ternary ? "C-Suite" : "VP" maps true → C-Suite, false → VP
Tips to get better generations
Reference columns with / in your description so the generator links the right fields
Be explicit about outputs: “Output exactly C-Suite else VP”
List patterns you care about: “CRO, Chief Revenue Officer, CEO, Founder, Co-Founder”
Say if you want case-insensitive: “case insensitive” (though Clay usually adds i by default)
Mention null handling: “treat missing titles as blank strings”
Example prompt that tends to generate very clean code:
Use /title_primary and /title_secondary.
Create a case-insensitive check.
If either title contains CRO, Chief Revenue Officer, CEO, Founder, or Co-Founder
then return "C-Suite" otherwise return "VP".
Treat missing values as empty strings.
Common gotchas (fix in 5 seconds)
Smart quotes: replace “ ” with straight quotes "" in formulas
Exact column names: your /field must match or be selected from the picker
Nulls: keep || "" — it prevents .toLowerCase() from blowing up on null
Hyphens/spaces in regex: use [-\s]? to match “cofounder”, “co-founder”, or “co founder”
When you outgrow the generator (manual polish)
Even after a good generation, you’ll often make small upgrades:
1) Add a word-boundary to avoid false positives
/\b(cro|chief revenue officer|ceo|co[-\s]?founder|founder)\b/i
This avoids matching “micro” (which contains “cro”).
2) Normalize once, reuse twice
const t1 = ({{Title - People - Results}}||"").toLowerCase();
const t2 = ({{Title - Peoples}}||"").toLowerCase();
const text = `${t1} ${t2}`;
return /\b(cro|chief revenue officer|ceo|co[-\s]?founder|founder)\b/i.test(text) ? "C-Suite" : "VP";
In a Clay Column → Formula, you can write the one-liner version; in Transform steps that allow multi-line JS, you can use const and return.
Bonus: the same approach for your URL cleaner
If you prefer to describe first, you can also generate the URL cleanup with /website:
Describe:
take /website
make it lowercase
remove http:// or https:// and optional www.
then return only the domain before the first slash
Generator will produce something close to:
({{Website}}||"")
.toLowerCase()
.replace(/^https?:\/\/(www\.)?/, "")
.split("/")[0]
(That’s your working formula — perfect.)
Quick reference — what things are called
{{Field Name}} → Clay variable (raw formula mode)
/field-name → Field reference (in the Describe generator prompt)
|| "" → fallback operator (“use blank if missing”)
.toLowerCase(), .replace(), .split() → string methods
/.../i → regex literal (the i is a flag)
.test(text) → regex test returns true/false
condition ? A : B → ternary operator (shorthand if/else)
📝 Notes
Do I totally understand every piece of these formulas? No.
That’s why Clay gives us the Describe/Generate assistant — it translates plain English into code.
But the more I peek under the hood, the less scary the symbols look. Each one is just a Lego block I can start to recognize.
⚡ Outcome
I don’t need to be a full-on developer to use Clay. But knowing what I’m looking at — {{variables}}, regex, string methods — gives me the confidence to tweak, combine, and push myself a little further into fluently speaking “computer language.”