Calculated Fields

17 custom dimension formulas for Data Studio marketing dashboards (checked and fixed for 2026)

The 17 custom dimension formulas I use most in marketing and SEO dashboards, from extracting domains and directories to intent labels, branded splits and a GA4 + Search Console join key, each fixed and checked against Google's current function list.

Lazarina Stoy·

17 Custom Dimension Formulas for Data Studio Marketing Dashboards

A custom dimension in Data Studio is a calculated field you create with Add a field: you give it a name and a formula, and it labels, cleans or groups the values already in your data source. Below are the 17 formulas I use most for marketing and SEO dashboards, each with the use case, the copy-paste formula and what to swap in for your own data.

I first published these in 2022. Since then Universal Analytics has gone, Data Studio (formerly Looker Studio) has added Group and Bin fields that do some of this without a formula, DATE_DIFF has become a legacy function, and I found bugs in several of my own formulas. Every formula below is the corrected version, checked against Google’s function documentation on 21 October 2026, and each section says what changed.

The 17 formulas at a glance

“Works on” is the source each was written for; most work on any source with a field of the same type.

# What it gives you Main functions Works on Output
1 The domain (brand) from a URL REGEXP_REPLACE, REGEXP_EXTRACT, TRIM SERP or rank-tracker exports Text dimension
2 Top-level directory or subdirectory REGEXP_EXTRACT Any URL or path field Text dimension
3 Ranking position buckets CASE, CAST (or a Bin field) Rank trackers; Search Console Text dimension (metric on Search Console)
4 URLs grouped by page section CASE, REGEXP_CONTAINS Crawls, Search Console, GA4 Text dimension
5 URLs segmented by language CASE, CONTAINS_TEXT Any URL or path field Text dimension
6 Queries labelled by search intent CASE, REGEXP_CONTAINS Search Console, keyword lists Text dimension
7 Frequency bands from a date CASE, DATETIME_DIFF, TODAY Crawl or URL Inspection data Text dimension
8 Two blended fields compared CASE, IS NULL Blends Chart-specific dimension
9 QoQ / YoY with date-limited blend tables Blend settings GA4, any dated source Blended metrics
10 Branded vs non-branded keywords CASE, REGEXP_CONTAINS Search Console, Google Ads, GA4 Text dimension
11 On-page quality labels (title, H1, meta) CASE, LENGTH Crawls, GA4 Text dimension
12 Traffic type by country CASE, AND GA4 Text dimension
13 Free vs paid traffic CASE, REGEXP_MATCH GA4 Text dimension
14 Numeric values in discrete buckets CASE (or a Bin field) Sheets, BigQuery, ecommerce exports Text dimension
15 YouTube labels from title and length CASE, REGEXP_MATCH, AND/OR YouTube data exports Text dimension
16 A target evaluated with a parameter CASE, parameter GA4, Google Ads Metric
17 A landing page key to blend GA4 and Search Console CONCAT, REGEXP_EXTRACT, REGEXP_REPLACE GA4 + Search Console Text dimension (join key)

How to create a custom dimension, and the rules every formula here follows

A calculated field is a field you create by applying functions, operators or branching logic to the fields you already have. It shows up as a dimension or a metric depending on what the formula returns. “Custom dimension” is the everyday name for the dimension kind.

  1. Open the data source (Resource › Manage added data sources › Edit), or the Data panel while you edit a report.
  2. Click Add a field, then Add calculated field. The same menu has Add group and Add bin, which come up in formulas 3, 4 and 14.
  3. Name the field, paste the formula, and replace my field names with yours. Fields turn green in the editor when Data Studio recognises them.
  4. When the editor accepts the formula, click Save. Calculated fields show an fx symbol in the field list.

You can also add a field to one chart (Add dimension › Create field in its Setup tab). Chart-specific fields need Field Editing in Reports switched on, exist only in that chart, and are the only kind that works on blended data. My piece on data sources and what you can edit in them covers who can change what.

Five rules that stop most of these formulas breaking

  1. CASE stops at the first true WHEN. Google’s documentation is explicit: the remaining WHEN clauses and the ELSE aren’t evaluated. The order of your WHENs is the classification, which is why formula 6 changed.
  2. REGEXP_MATCH matches the whole value; REGEXP_CONTAINS matches any part. REGEXP_MATCH(Query, "seo") is false for “seo tools”. Use CONTAINS unless you mean the entire value.
  3. Escape backslashes, or use a raw string. Data Studio uses Google’s RE2 syntax, and a backslash inside a normal string needs doubling ("\\." for a literal dot). A raw string, R"\.", takes it as written. I use raw strings for anything with \b or \..
  4. Never end a pipe list with |. An empty alternative matches everything. Google’s own regex page warns against it, and my 2022 intent formula had one.
  5. A formula built on a metric gives you a metric. GA4, Google Ads and Search Console metrics arrive already aggregated, so a CASE on Average Position or Key events can label rows in a table, but you can’t filter or group by it. Formula 3b and formula 16 are like that on purpose.
One query, best seo tools for agencies, moving down a CASE statement: the brand and informational WHEN clauses are false, the commercial WHEN is true and returns Commercial Intent, and the transactional WHEN and ELSE are never evaluated
CASE returns the first true WHEN. Source: Google’s CASE (searched) documentation, read 21 October 2026.

Before you write a CASE at all, check whether a Group field (fixed labels for text values) or a Bin field (numeric ranges) does the job. Google describes both as ways to group values “without needing to develop CASE WHEN expressions”, with up to 195 groups or bins per field.

Decision diagram: text dimensions use a Group field for fixed values or CASE for patterns; number dimensions use a Bin field for ranges or CASE with comparisons; metrics can be labelled with CASE but the result stays a metric that can't be filtered
Which field type for a label: Group, Bin, CASE, or a filter on the metric. From Google’s custom group, custom bin and calculated field pages.

1. Extract the brand (domain) from a URL

When doing competitor analysis at scale or SERP analysis, it’s very useful to visualise your data in a user-friendly way. One such instance is trimming the URLs ranking for a set of queries down to the brand name, so you can visualise share of voice per competitor. I’ve built this into the ML-enabled SERP analysis template too.

Create a custom dimension called “Brand name” with the formula below. Replace URL with any field from your data source that contains a URL or web address.

The Data Studio formula editor with a field named Brand Name and the TRIM, REGEXP_EXTRACT and nested REGEXP_REPLACE formula applied to a green URL field
The Brand name field in the formula editor, as I built it in 2022. View full size
TRIM(REGEXP_EXTRACT(REGEXP_REPLACE(REGEXP_REPLACE(URL, "https?://", ""), R"^(w{3}\.)?", ""), "([^/?]+)"))

Reading it from the inside out: strip the protocol, strip a leading www., then keep everything up to the first slash or question mark. The result is the domain, so https://www.example.com/blog/ becomes example.com. The same thing in one function, if you prefer it:

REGEXP_EXTRACT(URL, R"^(?:https?://)?(?:www\.)?([^/?#:]+)")

Subdomains stay in (shop.example.com); merge them with a Group field if they’re the same competitor.

2. Extract the top-level directory or a subdirectory from a URL

Extracting the top-level directory is useful not only when analysing your own website, but also for competitor or SERP analysis. It shows how competitors structure their top-level directories around the terms that matter to you, and whether there are insights to be gained from that.

The formula editor with a field named Top Level Directory and a REGEXP_EXTRACT formula on the URL field
The Top Level Directory field, 2022 version (https only). View full size

Here’s the formula. Again, replace URL with any field that contains a full URL. I’ve changed https to https? so http:// addresses match too; otherwise it’s the same pattern Google uses as its own example.

REGEXP_EXTRACT(URL, '^https?://[^/]+/([^/]+)/')

It returns blog for https://site.com/blog/post/, and null for a top-level page like /about, which isn’t in a directory.

If you instead want the subdirectory, use this one on a path field such as GA4’s Landing page. I’ve added the ^ anchor so it can’t drift into the domain when someone feeds it a full URL.

REGEXP_EXTRACT(Landing page, '^/[^/]+/([^/]+)/')

Extracting a subdirectory is really useful to replicate a behaviour flow chart, track internal links, or see how search and traffic metrics relate on a larger website. I’ve found it useful when auditing bigger sites, too.

3. Create custom buckets for ranking positions

Custom buckets for position (or rank) results are a great way to communicate the scale of your ranking keywords or URLs. They give you a top-level view of ranking performance at a glance.

Replace Rank Absolute with the keyword rank from your rank tracker (Nightwatch, Ahrefs, Semrush or any equivalent). I use these same buckets in my Nightwatch rank tracking dashboard. This version is the one to use now:

CASE
  WHEN CAST(Rank Absolute AS NUMBER) <= 3 THEN "Page 1: Positions 1 - 3"
  WHEN CAST(Rank Absolute AS NUMBER) <= 10 THEN "Page 1: Positions 4 - 10"
  WHEN CAST(Rank Absolute AS NUMBER) <= 20 THEN "Page 2: Positions 11 - 20"
  WHEN CAST(Rank Absolute AS NUMBER) <= 50 THEN "Positions 21 - 50"
  WHEN CAST(Rank Absolute AS NUMBER) <= 100 THEN "Positions 51 - 100"
  ELSE "Not in the top 100"
END

What I fixed. My 2022 version matched the rank as text, and the last two lines were wrong: "[21-50]" is a character class (any single digit 0–5, 1 or 2), not the numbers 21 to 50, and "[51-100]*" matches anything at all. A rank of 61 or 100 landed in “21 – 50”. Casting to a number and comparing with <= avoids regex entirely, and because CASE stops at the first true WHEN, each line only needs its upper limit. If the rank is already a Number field, drop the CAST. If you’d rather keep regex, the two lines become REGEXP_MATCH(Rank Absolute, "2[1-9]|[34][0-9]|50") and REGEXP_MATCH(Rank Absolute, "5[1-9]|[6-9][0-9]|100").

No-formula option: if the rank is a numeric dimension, a Bin field with custom breakpoints at 4, 11, 21, 51 and 101 gives you the same buckets from a menu.

This type of field lets you build charts like this one when you have competitor SERP data. The chart shows eight competitors’ distribution by ranking position, answering two questions:

  • Which competitors have the most URLs ranking on page 1 (positions 1–3), page 1 (positions 4–10), and so on?
  • From the collected SERP data, how are results distributed across the position groups (for example, the fewest results were collected for positions 51–100)?
Grouped column chart with five position buckets on the x-axis, from Page 1 positions 1 to 3 through positions 51 to 100, and one coloured column per competitor showing how many of its URLs rank in each bucket
Eight competitors’ ranking URLs split by position bucket, from SERP data. View full size

3b. Label average positions in groups with Search Console data

The field above only works on a dimension: rank as text or a number per row, as you get from a rank tracker like Nightwatch, SE Ranking or Oncrawl. If you want to use Search Console’s Average Position metric instead, build the label on the metric:

CASE
  WHEN Average Position >= 1 AND Average Position < 3 THEN "Money Keywords - Protect"
  WHEN Average Position >= 3 AND Average Position < 10 THEN "High value Keywords - Prioritize improvements"
  WHEN Average Position >= 10 AND Average Position < 20 THEN "Striking Distance Keywords - Improve"
  ELSE "Position 20+ - Monitor"
END
The formula editor with a field named Query breakdown: a CASE statement on the Average Position metric with three WHEN clauses for money, high value and striking distance keywords
The Query breakdown field on Search Console’s Average Position metric. View full size

I’ve added an ELSE so queries past position 20 get a label instead of a blank. As this is saved as a calculated metric, not a dimension, you’re a bit limited in the visualisations. I think the best place for it is a table, as below, which is also great for exporting and working on the data in Google Sheets.

A Data Studio table titled Query Breakdown with columns Query, Landing Page, Url Clicks, Average Position and Query breakdown, every visible row labelled Striking Distance Keywords - Improve
A query table sorted by the Query breakdown label, my own site’s Search Console data. View full size

The one limitation here is that you can’t use this calculated metric in a filter control for a cleaner look; you can only sort by it. Because it’s a metric, a Bin field won’t work on it either (bins need a numeric dimension). My piece on filter controls explains why. One workaround: create a flag field for each category with the logic “if it matches X label, then 1, else 0”, and use it in a chart filter, or sort by it.

4. Group URLs by page section

When you’re working with a big website, or a site run by a siloed organisation where different teams own different parts of it, you need to be able to split the data into page sections.

This is also very useful for spotting technical issues, such as Core Web Vitals problems caused by images used section-wide, or by section-specific templates. You can see this filter in action in my Core Web Vitals auditor dashboard.

The formula editor with a field named Page Section: a CASE statement with REGEXP_CONTAINS lines on the Address field labelling blog posts, white papers, branded pages, services pages, tag pages and paginated URLs
The Page Section field on a crawl’s Address field. View full size

Here’s the formula for copy-pasting. Replace Address with any field that contains a URL, and only include terms in the regex that actually appear in your URLs. Some adjusting is needed to make it specific to your site.

CASE
  WHEN REGEXP_CONTAINS(Address, "blog") THEN "Blog Posts"
  WHEN REGEXP_CONTAINS(Address, "white-papers|news|case-studies|insights") THEN "White papers, Case studies, News, Insights"
  WHEN REGEXP_CONTAINS(Address, "careers|about-us|contact|job-opportunities|clients|reviews|our-work|our-team|join-team") THEN "Branded Pages"
  WHEN REGEXP_CONTAINS(Address, "hospitality-travel-tourism|expertise|economic-development|energy|higher-education|technology|financial-services") THEN "Services Pages"
  WHEN REGEXP_CONTAINS(Address, "tag") THEN "Tag Pages"
  WHEN REGEXP_CONTAINS(Address, "/page") THEN "Paginated"
  ELSE "Unclassified"
END

What I fixed: the 2022 version was missing its closing END, so it wouldn’t save. Order matters here too: a blog post with “tag” in its slug is a Blog Post, because that line comes first. If your sections are cleanly separated by the first folder, a Group field on formula 2’s output does the same job without regex.

A fixed-size list control headed Page Section and Record Count, listing White papers and case studies 353, Unclassified 20, Tag Pages 711, Services Pages 27, Branded Pages 19 and Blog Posts 1.5K
The Page Section field in a fixed-size list control, with record counts. View full size

The end result gives you a quick overview of the split of URLs per page section, next to any metric you choose. In the example it’s Record Count, but it can be Clicks, Impressions or Sessions, depending on your data source.

5. Segment URLs by language

When you’re working with an international website that has versions of pages in several languages, you’ll often want to report on each language separately.

To do this, create a CASE formula that sorts the URLs by language version and gives each a user-friendly label you can use in a filter. That way, your dashboard users decide which URLs they see.

The formula editor with a field named Lang Filter using CONTAINS_TEXT on Landing Page for /es/, /fr/ and /de/, above a control listing English 10.6K, German 736, French 458 and Spanish 0 URL clicks
The Lang Filter field and the control it feeds. View full size

Here is the formula in text format. The landing page field can be replaced with any address or URL field in your data source, and the language folders will depend on the site you’re reporting on.

CASE
  WHEN CONTAINS_TEXT(Landing Page, "/es/") THEN "Spanish"
  WHEN CONTAINS_TEXT(Landing Page, "/fr/") THEN "French"
  WHEN CONTAINS_TEXT(Landing Page, "/de/") THEN "German"
  WHEN CONTAINS_TEXT(Landing Page, "/it/") THEN "Italian"
  ELSE "English"
END

This one needed no fix. It also works as a Group field: contains “/es/” and so on, with the remaining values grouped as English.

A chart splitting a metric by the language label created by the Lang Filter field
A metric split by language version. View full size

After creating this field, you can see a split of a metric of your choice (clicks, impressions, record count, sessions) for each language version, which helps you prioritise recommendations or get a more nuanced view of country-level performance.

6. Label the queries you rank for by search intent

This field is inspired by my Search Intent Classification dashboard, where I used filters to show only the keywords matching a condition.

That’s a somewhat limiting approach, though, because the keywords that don’t match are left out of the visualisations entirely.

Instead, a CASE field segments every keyword with regex, so the dashboard user can show keywords for a particular intent, or the ones that fall into none of the categories.

Bear in mind this is the most basic form of the classification, and it can be enhanced (like, a lot!) with the specific words that signal each intent in your industry. If you want to go further, read about how to do search intent classification better, or internationally and in different industries.

And here is the formula:

CASE
  WHEN REGEXP_CONTAINS(Query, R"(?i)\b(brandname|brand name variation|brandname\.com)\b") THEN "Navigational"
  WHEN REGEXP_CONTAINS(Query, R"(?i)\b(how|why|does|which|when|who|guide|tutorial|tutorials|learn|example|examples|resource|resources|ideas|tips|difference between|strategies|strategy|ways|directory|directories|pictures|samples|sample|plans|plan|news|basics|concepts|troubleshoot|issue|resolve|risks|beginners|beginner|beginner's|beginner’s guide|upgrade|improve|optimize|case study|get|best practices|templates|template|pros|cons|about|actionable|analysis|articles|ask|audit|avoid|become|benefits|blogs|build|calculate|campaign|choose|common|consider|cost|create|deal with|decrease|definition|definitive|definite guide|earn|easy|essential|events|explainer video|factors|facts|find|fix|get better|get more|graph|great|grow|hacks|highest rated|hot|ideal|importance of|increase|infographic|information|know|many|meaning|measure|meme|metrics|mistakes|most|myths|opportunity|popular|practices|questions|quotes|remove|set up|shortcuts|stats|study|successful|tactics|techniques|terms|that get|things|time|trends|tricks|types|unknown|updates|used|well|whether|whose|worst|framework|checklist|process|test|formula|glossary|scripts|survey|exercises|report|certification|webinar|calendar|quiz|form|things to do|to do|design|designs|not working)\b") THEN "Informational Intent"
  WHEN REGEXP_CONTAINS(Query, R"(?i)\b(best|top|vs|review|reviews|comparison|builder|builders|maker|creator|editor|editors|generator|plugin|plugins|services|service|app|apps|estimator|checker|planner)\b") THEN "Commercial Intent"
  WHEN REGEXP_CONTAINS(Query, R"(?i)\b(buy|prices?|pricing|cheap|cheapest|expensive|recommendation|recommended|near me|firm|firms|coupon|order|purchase|stores?|enterprise|calculator|wordpress|chrome extension|appliances?|free|affordable|best range|ratings|online|courses?|discount|for sale)\b") THEN "Transactional Intent"
  WHEN REGEXP_CONTAINS(Query, R"(?i:\b(alabama|alaska|arizona|arkansas|california|colorado|connecticut|delaware|florida|georgia|hawaii|idaho|illinois|indiana|iowa|kansas|kentucky|louisiana|maine|maryland|massachusetts|michigan|minnesota|mississippi|missouri|montana|nebraska|nevada|new hampshire|new jersey|new mexico|new york|north carolina|north dakota|ohio|oklahoma|oregon|pennsylvania|rhode island|south carolina|south dakota|tennessee|texas|utah|vermont|virginia|washington|west virginia|wisconsin|wyoming)\b)|\b(AL|AK|AZ|AR|CA|CO|CT|DE|FL|GA|HI|ID|IL|IN|IA|KS|KY|LA|ME|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|OH|OK|OR|PA|RI|SC|SD|TN|TX|UT|VT|VA|WA|WV|WI|WY)\b") THEN "Localised - US"
  ELSE "Unclassified"
END

What I fixed, and why it matters more than it looks:

  • The last list ended in a pipe. An empty alternative matches every string, so every query that reached that line was labelled “Localised – US”.
  • Terms sat in two buckets. “best” was in the informational list, which ran first, so no query ever reached Commercial through “best”. Same for “top” and “cheap” between Commercial and Transactional. Each term now lives in one bucket.
  • Navigational moved to the top. A query with your brand in it is navigational whatever else it contains.
  • Word boundaries and case. \b stops “how” matching “show”, and (?i) ignores capitals. State abbreviations only match in capitals, because “in”, “or” and “me” are everyday words.
  • An ELSE, so unclassified queries form a group you can review.

Combined with the branded vs non-branded field (formula 10), this gets you much more detail out of Search Console reporting, with views like these:

Three Search Console charts: keyword impressions by average position, a column chart of impressions by search intent split into branded and non-branded, and a bubble chart of intent categories by average position and impressions with a definitions panel
Search intent labels applied to Search Console queries, combined with the branded split. View full size

7. Create a frequency field from a date

Your data source often has a date field, but a date on its own makes scale hard to see, especially when there are time thresholds your stakeholders understand better than raw dates.

Here is the current version. Replace Last Crawl with any Date field in your data source, and adjust the labels.

CASE
  WHEN DATETIME_DIFF(TODAY(), Last Crawl, DAY) < 30 THEN "Crawled Last 30 days"
  WHEN DATETIME_DIFF(TODAY(), Last Crawl, DAY) < 60 THEN "Crawled Last 60 days"
  WHEN DATETIME_DIFF(TODAY(), Last Crawl, DAY) < 90 THEN "Crawled Last 90 days"
  WHEN DATETIME_DIFF(TODAY(), Last Crawl, DAY) < 180 THEN "Crawled Last 180 days"
  ELSE "Crawled Last 180+ Days"
END
The formula editor with a field named Crawl Frequency: a CASE statement using DATE_DIFF between TODAY and the Last Crawl field, with bands at 30, 60, 90 and 180 days
The 2022 Crawl Frequency field, built with DATE_DIFF. View full size

What changed: the 2022 version used DATE_DIFF(TODAY(), Last Crawl). Google now marks DATE_DIFF as supporting only old “compatibility mode” date fields, and recommends DATETIME_DIFF on proper Date or Date & Time fields. If your date arrives as text (common in crawl exports pasted into Sheets), set the field’s type to Date in the data source first. TODAY() uses UTC unless you give it a timezone, as in TODAY("Europe/London").

To see this field in action, open my URL Inspection API dashboard.

8. Compare two fields from two different datasets

Comparative analysis in Data Studio can get complex, especially given the limitations of data blending. Here’s a simple way to compare two datasets and surface the differences between them.

You need two datasets with the same structure. In the screenshots I used two Screaming Frog SEO Spider exports with the same fields: one crawl of the mobile version of the site, one of the desktop version.

Blend the data first, with the URL address as the join key. Add the two fields you want to compare, and name the blend accordingly.

The Blend Data panel with two crawl data sources joined on Address, Meta Robots Desktop from one and Meta Robots Mobile from the other, above a report showing a Meta Robots Tags table and a pass and fail bar chart
The two crawls blended on Address, with the meta robots field from each. View full size

Then create a table showing the three fields side by side: the join key (the address) and the two fields (the mobile and desktop values).

Now add a “Comparison” dimension. This is where the CASE formula comes in. Select the table, click Add dimension › Create field, and use this format:

CASE
  WHEN Dimension 1 = Dimension 2 THEN "text"
  ELSE "other text"
END

In our case, the formula looks like this:

CASE
  WHEN Meta Robots Mobile = Meta Robots Desktop THEN "pass"
  ELSE "fail"
END

It compares the two fields and returns the text you set for each condition. It has to be a chart-specific field: Google’s documentation says data source calculated fields can’t be used with blended data, and a field inside one blend table can only see that table’s fields.

To count passes and fails, use Record Count as the metric, or add the Comparison field as a metric and change its aggregation from Count Distinct (which only ever shows 2) to Count. A fixed-size list control on the field lets users filter the table.

A horizontal bar chart of the Comparison field showing about 4.1 thousand pass rows and 277 fail rows, next to a fixed-size list control with the same counts
Pass and fail counts, with a control to filter the table. View full size

There are some limits to blending data and creating a custom dimension on a blend:

  • A blend can join at most five tables.
  • The comparison field exists only in the chart you create it in. To reuse it, copy the chart.
  • You can’t point a filter control at a chart-specific field on a blend (this is reported by users rather than stated by Google). Build the condition into the CASE instead, as below.

If you want rows where both crawls are empty to count as a pass, add an IS NULL condition joined with AND:

CASE
  WHEN Meta Robots Mobile IS NULL AND Meta Robots Desktop IS NULL THEN "pass"
  WHEN Meta Robots Mobile = Meta Robots Desktop THEN "pass"
  ELSE "fail"
END

Without that first line, two blanks fall through to “fail”, because comparing null with null isn’t true.

9. Build a QoQ or YoY report with date-limited blend tables

Another use of this kind of blend is year-over-year or quarter-over-quarter reporting, explained in this sample report by Nimantha. It’s the same idea, except you blend four or five copies of one data source and limit each table to its own date range in the blend settings.

The Blend Data panel with four tables from the same GA4 source joined on Quarter, Page Section and Country, each with one metric renamed 2019 NBL to 2022 NBL and its own custom date range
Four tables, one per year, each with its own custom date range. View full size

The end result can be a pivot table showing the year-over-year difference in quarterly performance, combined here with the page section breakdown from formula 4.

When you don’t need a blend now: for “vs previous period” or “vs last year”, charts have a comparison date range built in. The blend is still the way to show three or four years side by side.

10. Split keywords into branded and non-branded

This is a useful formula to have for any data source with a keyword or query field, not only search or website analytics. It’s also handy in keyword research, to separate navigational queries from the rest.

Make sure to include every brand name variation, misspellings included. Replace Query with Search Console’s Query, a Google Ads keyword, or GA4’s Session manual term.

CASE
  WHEN REGEXP_CONTAINS(Query, R"(?i)brandname|brand name|brnadname") THEN "Branded"
  WHEN REGEXP_CONTAINS(Query, R"\((not provided|not set|unavailable)\)") THEN "Not specified"
  ELSE "Non-Branded"
END

What I fixed: the 2022 version had brand^ in it. ^ means “start of the value”, so after other characters it can never match; if you meant “starts with”, write ^brand. I also escaped the brackets around “(not set)”, added (?i) so capitals don’t matter, and swapped the old Multi-Channel Funnels keyword field, which went with Universal Analytics in 2023.

It’s the first field I add after connecting Search Console.

11. Label titles, meta descriptions and H1s by length

Three donut charts from a Sitebulb crawl showing the share of pages labelled Title too long, Perfect, good or too short, the same for H1s, and meta descriptions all too short
On-page quality labels from a crawl, one donut per element. View full size

This view uses three fields. The first is the title tag evaluation:

CASE
  WHEN Title Length >= 50 AND Title Length <= 60 THEN "Title - Perfect"
  WHEN Title Length >= 40 AND Title Length <= 50 THEN "Title - good"
  WHEN Title Length < 40 THEN "Title - too short"
  WHEN Title Length > 60 THEN "Title too long"
END

In GA4, where there’s no length field, wrap the page title in LENGTH:

CASE
  WHEN LENGTH(Page title) >= 50 AND LENGTH(Page title) <= 60 THEN "Title - Perfect"
  WHEN LENGTH(Page title) >= 40 AND LENGTH(Page title) <= 50 THEN "Title - good"
  WHEN LENGTH(Page title) < 40 THEN "Title - too short"
  WHEN LENGTH(Page title) > 60 THEN "Title too long"
END

A title of exactly 50 characters matches the first two lines; CASE takes the first, so it’s “Perfect”. Here’s the view this can give you:

A donut chart of title assessment labels above a table of landing pages with page title, title SEO assessment, title length, sessions and engaged sessions, the longest titles highlighted
Title labels on GA4 data from my own site, with the offending pages listed underneath. View full size

The H1 evaluation:

CASE
  WHEN H1 Length >= 50 AND H1 Length <= 60 THEN "H1 - Perfect"
  WHEN H1 Length >= 40 AND H1 Length <= 50 THEN "H1 - good"
  WHEN H1 Length < 40 THEN "H1 - too short"
  WHEN H1 Length > 60 THEN "H1 - too long"
END

And the meta description evaluation:

CASE
  WHEN Meta Description Length >= 150 AND Meta Description Length <= 160 THEN "MD - Perfect"
  WHEN Meta Description Length >= 140 AND Meta Description Length <= 150 THEN "MD - good"
  WHEN Meta Description Length < 140 THEN "MD - too short"
  WHEN Meta Description Length > 160 THEN "MD - too long"
END

These fields are very useful once a technical crawl is in your report: Sitebulb, Oncrawl and Screaming Frog exports usually include the length fields. The ranges are my rules of thumb, not Google limits.

You get a quick, holistic view of the on-page opportunities, and with controls and tables you can deep-dive into the individual “offending pages” and export every URL with a title, H1 or meta description that’s too long or too short.

12. Create custom categories for traffic type and country

You can do this with a CASE statement and a logical AND. It’s useful for executive-level reporting, and for page-level or report-level filters on your most important markets. In GA4, the fields are Country ID (the two-letter ISO code) and Session medium:

CASE
  WHEN Country ID = "US" AND Session medium = "cpc" THEN "US - Paid"
  ELSE "other"
END

This is Google’s own CASE example, which still uses the Universal Analytics names Country ISO Code and Medium. Those don’t exist on GA4.

13. Show free versus paid traffic

A field that separates traffic you’ve paid for, like CPC, from everything else. Google’s documentation gives the simplest version, a check for inequality:

CASE
  WHEN Session medium != "cpc" THEN "free"
  ELSE "paid"
END

Of course, this can be more granular. Paid traffic arrives with more mediums than “cpc”, so for GA4 I now use the same pattern GA4’s own default channel groups use to decide what’s paid:

CASE
  WHEN REGEXP_MATCH(Session medium, "^(.*cp.*|ppc|retargeting|paid.*)$") THEN "paid"
  ELSE "free"
END

Written this way round, a row with no medium falls to the ELSE as “free” instead of being counted as “paid”. If GA4’s own groupings are enough, Session default channel group already splits Paid Search, Paid Social and the rest.

14. Classify numeric values into discrete buckets

This field is super useful for building user personas from purchase value in an ecommerce store. Once you have buckets, you can filter behaviour and acquisition data for each segment and make better decisions about targeting.

CASE
  WHEN Amount < 20 THEN "Small"
  WHEN Amount >= 20 AND Amount < 100 THEN "Medium"
  WHEN Amount >= 100 THEN "Large"
END

This works where Amount is a value on each row: an orders export in Google Sheets, BigQuery or a Shopify connector. On GA4, Purchase revenue is an aggregated metric, so this CASE gives you a metric too, not a segment you can filter by (rule 5 above). For row-level data, a Bin field with custom breakpoints at 20 and 100 does the same thing without a formula.

15. Label YouTube videos by title and length

This one uses a regular expression match with a logical AND/OR. It assumes a data source with the video title, a livestream flag and the length in seconds, such as a YouTube Data API export in Google Sheets; the field names will differ in yours.

CASE
  WHEN REGEXP_MATCH(Video Title, ".*Google Analytics.*")
       AND (is_livestream = TRUE OR Video Length > 600)
  THEN "GA Livestream or long video"
END

What I fixed: the pattern was ".*Google Analytics*", where the final * applies only to the “s”, so it only matched titles ending in “Google Analytic” or “Google Analytics” (REGEXP_MATCH needs the whole value to match). It’s now .*Google Analytics.*. I’ve also added brackets. Google’s operators page says to use them to force the order, and without them the usual rule (AND before OR) meant any video longer than ten minutes got the label whatever its title.

16. Evaluate a target with a parameter

This one evaluates a metric against a target you set. Say you’re running a campaign whose aim is conversions: create a number parameter for the target, then compare the recorded key events with it.

  1. In the data source or the report’s Data panel, click Add a parameter, set the data type to Number, call it “Target key events” and give it a default value.
  2. Create a calculated field with the formula below.
  3. To let viewers change the target, add a control to the report that uses the parameter.
CASE
  WHEN Key events >= Target key events THEN 1
  ELSE 0
END

GA4 renamed conversions to “key events”; on Google Ads use Conversions. The 1/0 result works well with conditional formatting, or swap in “On target” and “Below target”.

17. Create a landing page field to blend GA4 and Search Console data

To blend GA4 with Search Console, the landing pages have to match, and they don’t by default: Search Console gives full URLs, GA4 gives paths. There are two ways to make a join key.

Option A: add the domain to the GA4 path. GA4’s Landing page is the path of the first page in a session, for example /how-to-incorporate-machine-learning-into-your-serp-analysis/. Prepend your domain:

CONCAT("https://www.yoursite.com", Landing page)

Use your domain exactly as Search Console shows it. For several hostnames, use GA4’s Hostname; CONCAT now takes more than two arguments:

CONCAT("https://", Hostname, Landing page)

Option B: extract the path from Search Console’s full URL. Search Console gives landing pages as full URLs, such as https://www.mlforseo.com/machine-learning-implementation-guides/keyword-research/pytrends-google-trends-api-python/. This keeps everything after the domain and before any ? or #:

REGEXP_EXTRACT(Landing Page, R"^https?://[^/]+(/[^?#]*)")

What I fixed: the 2022 pattern needed at least one character after the slash, so the homepage came back null and dropped out of the join. I also used to strip the trailing slash on the assumption that GA4 stores paths without one. GA4 records the path as it was requested, so whether it ends in a slash depends on your site. Check a few rows on both sides, and if they differ, strip the slash from both so they always match:

REGEXP_REPLACE(Landing page, "/$", "")

Wrap the Search Console extraction the same way. Then create each key inside its own table in the blend (Add dimension › Create field in the blend editor), and join on it.

Three Data Studio tables: GA4 landing pages with views, Search Console short URLs with clicks, and the blended table joining both on the path, with the same PyTrends guide row highlighted in each and arrows showing the join
GA4 views and Search Console clicks joined on the cleaned path, on my own site. View full size

What I changed from the 2022 versions

If you copied any of these from my 2022 guide, this is what to update. Everything else is as it was.

# 2022 version Problem Now
2 ^https:// http URLs return null ^https?://, and a ^ anchor on the path version
3 Regex on rank text [21-50] and [51-100]* mislabel ranks 21–100 CAST to number and <=, or a Bin field
3b No ELSE Positions past 20 blank ELSE label added
4 No END Formula won’t save END added
6 Trailing |, shared terms, no boundaries Everything left over became “Localised – US”; Commercial rarely reached Pipe removed, one bucket per term, \b and (?i), ELSE
7 DATE_DIFF Legacy: compatibility-mode dates only DATETIME_DIFF(…, DAY)
10 brand^, MCF keyword Dead alternative; UA field retired (?i), escaped brackets, GA4 fields
12–13 UA field names Fields don’t exist on GA4 Country ID, Session medium; paid regex from GA4’s channel rules
13–16 Missing spaces (WHENMedium) Syntax errors Spaces restored
15 Analytics*, no brackets Pattern and AND/OR precedence .*Google Analytics.*, brackets
16 Conversions Renamed in GA4 Key events and a number parameter
17 (/[^?#]+), slash stripped on one side Homepage null; slash mismatch (/[^?#]*), normalise both sides

Universal Analytics names to swap if you’re moving an old report to GA4:

Universal Analytics field GA4 field Used in
Medium Session medium 12, 13
Country ISO Code Country ID 12
Goal completions / Conversions Key events 16
Keyword (Multi-Channel Funnels) Session manual term, or Session Google Ads keyword text 10
Landing Page Landing page (path only), or Landing page + query string 2, 17

Templates to try these formulas on

Try formulas 3b, 4, 6 and 10 on a copy of one of these:

Further reading

Where to go next

Frequently asked questions

How do I create a custom dimension in Data Studio?

Open the data source (or the Data panel in a report), click Add a field, then Add calculated field. Name it, write the formula and save. For a field that only one chart needs, use Add dimension › Create field in that chart’s Setup tab.

What are calculated fields in Data Studio?

Fields you create by applying functions, operators or branching logic such as CASE to your data. A calculated field becomes a dimension or a metric depending on what the formula returns.

How do I find which fields are custom?

Calculated fields, groups and bins show an fx symbol next to their name in the data source’s field list. Click it to open the formula.

What is the CASE statement?

CASE checks conditions in order and returns the result of the first one that’s true, like an if-then-else. If none is true, it returns the ELSE value, or null when there’s no ELSE. The format is CASE WHEN condition THEN result [WHEN … THEN …] [ELSE result] END.

What can a CASE formula do in a marketing report?

Relabel values so readers understand them (“P1” becomes “Phase 1: Exploration”), add context (queries containing the brand become “Branded”), tag values that meet a condition (URLs containing /fr/ become “French”), create a dimension to filter on that doesn’t exist in the source (page section), and match a client’s own reporting structure, such as custom quarters.

Shopping Cart
Scroll to Top