Skip to content
Coding Script or NotebookGoogle ColabFree

Multi-Dimension Query Classifier: Rule-Based Colab Notebook and Google Sheets Template

ForSearch intentKeyword research

By Lazarina Stoy· Updated 24 Oct 2026

Most keyword tools give each query one search intent label and stop there. A single query says much more than that: whether the searcher is a beginner, whether they want a video or a template, whether location matters, whether they are trying to fix something. This free rule-based classifier reads every keyword in your export and adds a column for each of those dimensions, using regex rules you can open and change.

What it labels

  • Query length in words
  • Main intent: informational, commercial, transactional, navigational (more than one if several match)
  • Query type: Do, Know or Go
  • Geo relevance, device relevance and an explicit content format (video, infographic, template, document, webinar, podcast, eBook)
  • Knowledge level (beginner, intermediate, expert) and user persona (student, professional, casual user, budget-conscious, affluent and more)
  • Implicit problem (“how to fix”, “won’t work”) and context such as urgency or mood

Who it’s for

SEOs and content strategists who want richer intent labels on a keyword set without paying for another tool, and without needing to write Python. If you can upload a CSV, you can run it.

How to use it

  1. Open the notebook in Google Colab and save a copy to your own Drive.
  2. Export your keywords from Semrush, Ahrefs or Search Console as a CSV with a Keyword column.
  3. Run the first code cell. It asks you to upload the CSV, then applies each labelling function to the Keyword column and shows the first rows.
  4. Run the last cell to download updated_file.csv with all the new columns.
  5. Edit the regex lists for your industry (your brand names, your product words) and run it again.

Prefer spreadsheets? The Google Sheets version does the same with formulas. Make a copy: it has a demo tab of about 3,950 “first time dog owner” keywords, a tab that shows each formula, and the notebook’s output for comparison.

For intent alone, there is also a refreshed rule-based classifier on GitHub that matches whole words, keeps every matching intent (multi-label), flags easy keywords (difficulty under 65) and money keywords (CPC of $0.01 or more), and prints the same rules as a Google Sheets IFS(REGEXMATCH()) formula and a Data Studio calculated field.

What you get

Your keyword export back as a CSV with ten extra columns you can pivot, filter and chart, plus rules you can audit line by line.

Limits

  • Rules only see the words in the query. A keyword like “chatbot benefits” says nothing explicit about intent, so it stays unclassified.
  • Navigational intent depends on brand names, so add yours and your competitors’.
  • The lists are English-only and some Sheet formulas match parts of words; the GitHub version fixes this with word boundaries.

Read the full method comparison in Search-Intent Classification with Machine Learning, and go deeper in the Semantic ML-enabled Keyword Research course.

What’s included

  • Adds ten label columns to any keyword export: query length, main intent, Do/Know/Go, geo, content format, knowledge level, persona, device, problem and context
  • Every rule is a plain regex pattern you can read and edit for your niche
  • Google Sheets version with the same logic as formulas, plus a demo tab of about 3,950 keywords
  • Refreshed GitHub classifier adds whole-word matching, easy/money keyword flags and prints a ready-to-paste Sheets formula and Data Studio calculated field
  • No API keys, no cost, runs in the browser
. Disclosure menus (APG pattern), hover intent, mobile dialog with focus trap, announcement dismiss, skip-link target, newsletter status message. No dependencies. */ (function () { 'use strict'; var d = document;/* ---------- skip link target: #main, else the page's
, else the first block after the header */ (function () { var mains = d.querySelectorAll('main'); if (mains.length > 1) { // Our post-content
plus another one: drop the landmark from ours. var ours = d.querySelector('main[data-mlfc-main]'); if (ours) { ours.setAttribute('role', 'none'); ours.removeAttribute('id'); } } var skip = d.querySelector('.mlfc-skip'); if (!skip) return; var t = d.getElementById('main'); if (!t || (t.getAttribute('role') === 'none')) { t = d.querySelector('main:not([role="none"]), [role="main"]'); if (!t) { var hd = skip.closest('.wp-block-template-part') || skip.closest('.mlfc-hdw'); t = hd && hd.nextElementSibling; } if (!t) return; if (!t.id) t.id = 'main'; skip.setAttribute('href', '#' + t.id); } if (!t.hasAttribute('tabindex')) t.setAttribute('tabindex', '-1'); skip.addEventListener('click', function () { setTimeout(function () { t.focus({ preventScroll: false }); }, 0); }); })();/* ---------- announcement dismiss */ d.querySelectorAll('[data-mlfc-ann]').forEach(function (bar) { var btn = bar.querySelector('[data-mlfc-ann-close]'); if (!btn) return; btn.addEventListener('click', function () { try { localStorage.setItem(bar.getAttribute('data-mlfc-ann'), '1'); } catch (e) {} var next = d.querySelector('.mlfc-logo'); bar.hidden = true; if (next) next.focus(); }); });/* ---------- disclosure dropdowns */ var items = [].slice.call(d.querySelectorAll('.mlfc-hdw [data-mlfc-dd]')); var fine = window.matchMedia && window.matchMedia('(hover: hover) and (pointer: fine)').matches; function btnOf(it) { return it.querySelector('button[aria-controls]'); } function panelOf(it) { return d.getElementById(btnOf(it).getAttribute('aria-controls')); } function isOpen(it) { return btnOf(it).getAttribute('aria-expanded') === 'true'; } function setOpen(it, open) { var b = btnOf(it), p = panelOf(it); if (!b || !p) return; b.setAttribute('aria-expanded', open ? 'true' : 'false'); p.hidden = !open; if (open) { // keep the panel inside the viewport p.style.left = ''; p.style.right = ''; var r = p.getBoundingClientRect(); if (r.right > window.innerWidth - 12) { p.style.left = 'auto'; p.style.right = '0'; } } } function closeAll(except) { items.forEach(function (it) { if (it !== except && isOpen(it)) setOpen(it, false); }); }items.forEach(function (it) { var b = btnOf(it), tIn, tOut; if (!b) return; b.addEventListener('click', function () { clearTimeout(tIn); clearTimeout(tOut); var open = !isOpen(it); closeAll(it); setOpen(it, open); }); if (fine) { // Hover intent: open after 300 ms, close 400 ms after the pointer leaves trigger + panel. it.addEventListener('mouseenter', function () { clearTimeout(tOut); tIn = setTimeout(function () { closeAll(it); setOpen(it, true); }, 300); }); it.addEventListener('mouseleave', function () { clearTimeout(tIn); tOut = setTimeout(function () { setOpen(it, false); }, 400); }); } it.addEventListener('focusout', function (e) { if (e.relatedTarget && !it.contains(e.relatedTarget)) setOpen(it, false); }); it.addEventListener('keydown', function (e) { if (e.key === 'Escape' && isOpen(it)) { e.stopPropagation(); setOpen(it, false); b.focus(); } }); }); d.addEventListener('click', function (e) { items.forEach(function (it) { if (isOpen(it) && !it.contains(e.target)) setOpen(it, false); }); }); d.addEventListener('keydown', function (e) { if (e.key !== 'Escape') return; items.forEach(function (it) { if (isOpen(it)) { setOpen(it, false); btnOf(it).focus(); } }); });/* ---------- mobile menu dialog */ var menuBtn = d.querySelector('.mlfc-menu-btn'); var dlg = d.getElementById('mlfc-mnav'); if (menuBtn && dlg) { var FOC = 'a[href],button:not([disabled]),input,select,textarea,[tabindex]:not([tabindex="-1"])'; var openMenu = function () { dlg.hidden = false; menuBtn.setAttribute('aria-expanded', 'true'); d.body.classList.add('mlfc-lock'); var c = dlg.querySelector('[data-mlfc-close]'); if (c) c.focus(); }; var closeMenu = function (restore) { if (dlg.hidden) return; dlg.hidden = true; menuBtn.setAttribute('aria-expanded', 'false'); d.body.classList.remove('mlfc-lock'); if (restore !== false) menuBtn.focus(); }; menuBtn.addEventListener('click', function () { dlg.hidden ? openMenu() : closeMenu(); }); dlg.querySelector('[data-mlfc-close]').addEventListener('click', function () { closeMenu(); }); dlg.addEventListener('keydown', function (e) { if (e.key === 'Escape') { e.preventDefault(); closeMenu(); return; } if (e.key !== 'Tab') return; var f = [].filter.call(dlg.querySelectorAll(FOC), function (el) { return el.offsetParent !== null || el === d.activeElement; }); if (!f.length) return; var first = f[0], last = f[f.length - 1]; if (e.shiftKey && d.activeElement === first) { e.preventDefault(); last.focus(); } else if (!e.shiftKey && d.activeElement === last) { e.preventDefault(); first.focus(); } }); // In-page links (e.g. #courses) close the menu first. dlg.addEventListener('click', function (e) { var a = e.target.closest && e.target.closest('a[href^="#"]'); if (a) closeMenu(false); }); var mq = window.matchMedia('(min-width: 1024px)'); var onMq = function () { if (mq.matches) closeMenu(false); }; if (mq.addEventListener) mq.addEventListener('change', onMq); else if (mq.addListener) mq.addListener(onMq); }/* ---------- newsletter: plain POST to Kit in a new tab (same pattern as mlfa2_newsletter()); say so in the live region */ d.querySelectorAll('form[data-mlfc-nl]').forEach(function (form) { var msg = form.querySelector('.mlfc-nl__msg'); form.addEventListener('submit', function () { if (msg) msg.textContent = 'Thanks. Kit opens in a new tab: confirm your subscription there and check your inbox.'; }); }); })();