{"id":10146,"date":"2026-08-30T08:09:00","date_gmt":"2026-08-30T06:09:00","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/?p=10146"},"modified":"2026-08-19T12:26:53","modified_gmt":"2026-08-19T10:26:53","slug":"tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api","status":"publish","type":"post","link":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/","title":{"rendered":"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API"},"content":{"rendered":"<p>The Search Console interface answers one query at a time. It shows the top rows, exports a thousand of them, and offers no way to ask whether visibility for a whole topic is rising while brand searches merely hold steady. That question needs the queries grouped, and grouping needs both more rows than the interface hands over and a place to define the groups.<\/p>\n<p>The following walkthrough builds that: pulling the data through the Search Console API, categorising queries with regular expressions in Looker Studio, and reading the resulting clusters \u2014 including an honest account of what this data cannot show about answers generated directly on the results page.<\/p>\n<figure class=\"lw-diagram\">\n<img decoding=\"async\" src=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/diagrams\/gsc-seo-dashboard-en.png\" width=\"1120\" height=\"580\" loading=\"lazy\" alt=\"Queries pulled from the Search Console API pass through one regex calculated field and drop into four buckets - brand, two topic clusters and an unmatched bucket - shown as fill levels\"><figcaption>The clusters answer how the site is found; the unmatched bucket is where the next cluster is hiding.<\/figcaption><\/figure>\n<h2>What the API Gives That the Interface Does Not<\/h2>\n<p>The performance report exports up to a thousand rows. The <code>searchanalytics.query<\/code> method of the API returns up to 25,000 per request and pages through the rest with <code>startRow<\/code>, which is the difference between seeing the head of the distribution and seeing the long tail where new topics first appear.<\/p>\n<pre class=\"wp-block-kevinbatdorf-code-block-pro\"><code>POST https:\/\/searchconsole.googleapis.com\/webmasters\/v3\/sites\/\n     https%3A%2F%2Fexample.com%2F\/searchAnalytics\/query\n\n{\n  \"startDate\": \"2026-07-01\",\n  \"endDate\": \"2026-07-31\",\n  \"dimensions\": [\"query\"],\n  \"rowLimit\": 25000,\n  \"startRow\": 0,\n  \"dimensionFilterGroups\": [{\n    \"filters\": [{\n      \"dimension\": \"query\",\n      \"operator\": \"includingRegex\",\n      \"expression\": \"(?i)(pricing|cost|licen[cs]e)\"\n    }]\n  }]\n}<\/code><\/pre>\n<p>For a dashboard, Looker Studio&#8217;s native Search Console connector calls the same API without any code, which is the practical route unless the data is being warehoused. Its one structural constraint is worth knowing before designing anything: the connector offers a site-level table where the query dimension exists and a URL-level table where the landing page exists, and <strong>query and landing page cannot be combined<\/strong>. That is a limitation of the Search Console data itself, not of the connector, and no calculated field works around it.<\/p>\n<h2>Two Regex Rules That Decide Whether Any of This Works<\/h2>\n<p>Both places where a regular expression can be written behave in a way that surprises people who know regex from elsewhere.<\/p>\n<p>Search Console uses <strong>RE2<\/strong>, which has no lookahead and no lookbehind. The familiar trick for non-brand \u2014 a negative lookahead excluding the brand name \u2014 simply fails to compile. The supported approach is the filter&#8217;s own inversion: a custom regex filter set to <em>doesn&#8217;t match<\/em>, with the brand pattern as the expression.<\/p>\n<p>Looker Studio&#8217;s <code>REGEXP_MATCH<\/code> requires the pattern to match the <strong>entire<\/strong> field value, not a fragment of it. A pattern of <code>acme<\/code> matches only the query that is exactly the word <em>acme<\/em>; matching any query containing it needs the wildcards spelled out:<\/p>\n<pre class=\"wp-block-kevinbatdorf-code-block-pro\"><code>-- Field: Brand vs non-brand\nCASE\n  WHEN REGEXP_MATCH(Query, '(?i).*(acme|acme corp|acmecorp|acme app).*')\n    THEN 'Brand'\n  ELSE 'Non-brand'\nEND<\/code><\/pre>\n<p>The <code>(?i)<\/code> flag makes the match case-insensitive in both systems. The brand alternation is worth over-populating from the start: misspellings, the spaced and unspaced form, and the product name all belong in the brand bucket, because every one of them left outside inflates the non-brand figure with searches that were never won on merit.<\/p>\n<h2>Turning Topics into Clusters<\/h2>\n<p>The same construction, extended, becomes the dimension the dashboard is built on. Order matters \u2014 the first matching branch wins, so brand belongs first, or a branded search for a feature lands in that feature&#8217;s cluster:<\/p>\n<pre class=\"wp-block-kevinbatdorf-code-block-pro\"><code>-- Field: Query cluster\nCASE\n  WHEN REGEXP_MATCH(Query, '(?i).*(acme|acmecorp).*')            THEN 'Brand'\n  WHEN REGEXP_MATCH(Query, '(?i).*(pricing|cost|how much).*')    THEN 'Pricing'\n  WHEN REGEXP_MATCH(Query, '(?i).*(integrat|api|webhook|sync).*') THEN 'Integrations'\n  WHEN REGEXP_MATCH(Query, '(?i).*(vs |alternative|compare).*')   THEN 'Comparison'\n  ELSE 'Unmatched'\nEND<\/code><\/pre>\n<p>Keeping an explicit <em>Unmatched<\/em> branch rather than a catch-all label is what makes the field maintainable. That bucket is a working queue: sorted by impressions, it lists the demand the taxonomy has not accounted for yet, and every cluster after the first two usually comes out of reading it.<\/p>\n<h2>Reading the Dashboard<\/h2>\n<p>A cluster dimension makes three charts sufficient. Impressions by cluster over time show whether visibility is broadening or concentrating. Clicks and CTR per cluster show whether that visibility converts into visits. A table of the unmatched queries feeds the next iteration of the taxonomy.<\/p>\n<p>The trap in this view is the brand cluster. Brand searches rise with awareness, with campaigns, and with seasonality, and they convert far better than anything else \u2014 so a total that looks healthy can hide non-brand clusters shrinking underneath it. Reporting brand and non-brand as separate lines rather than as one visibility total is what keeps that visible.<\/p>\n<h2>What This Data Cannot Say About Generative Results<\/h2>\n<p>Search Console has no dimension for AI-generated answers. Impressions that occurred inside a generative result are included in the same performance data as ordinary results, and there is no filter that separates them, so any dashboard claiming to measure generative visibility from this source is inferring rather than measuring.<\/p>\n<p>What the data does support is a pattern worth watching: an informational cluster whose impressions hold steady or grow while its clicks and CTR decline, over a period with no ranking loss to explain it. That shape is consistent with answers being satisfied on the results page. It is also consistent with a changed snippet or a shifted mix of queries within the cluster, which is why it belongs in a report as a question to investigate rather than a metric to present.<\/p>\n<h2>Staying Inside the Guardrails<\/h2>\n<p>Three properties of the source data limit what the dashboard can honestly claim. Rare queries are withheld entirely for privacy reasons, so the query rows will always sum to less than the property totals \u2014 the difference is not a bug to reconcile, and cluster shares should be read as shares of the queries that <em>are<\/em> reported.<\/p>\n<p>History stops at sixteen months, which makes year-over-year comparison possible but not a second year of it, so anything longer needs its own storage. And average position is already an impression-weighted average within each row; averaging those averages across a cluster produces a number that looks precise and means very little, which is why impressions and clicks carry the argument better than position does.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Getting more rows out of Search Console than the interface exports, splitting queries into brand and topic clusters with regex calculated fields in Looker Studio, and reading the result honestly \u2014 including what the data cannot say about generative search results.<\/p>\n","protected":false},"author":1,"featured_media":11407,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[127],"tags":[91386,91353,91094,91219,91252],"class_list":["post-10146","post","type-post","status-publish","format-standard","hentry","category-tutorials-en-digital-marketing","tag-marketing-cyfrowy-pl","tag-looker-studio","tag-seo","tag-tutorial","tag-web-analytics"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API - Lukas Wojcik - Blog<\/title>\n<meta name=\"description\" content=\"Getting more rows out of Search Console, splitting queries into clusters with regex fields, and reading what the data cannot say about AI results.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Getting more rows out of Search Console, splitting queries into clusters with regex fields, and reading what the data cannot say about AI results.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-30T06:09:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"luky\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"luky\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/\"},\"author\":{\"name\":\"luky\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"headline\":\"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API\",\"datePublished\":\"2026-08-30T06:09:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/\"},\"wordCount\":915,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png\",\"keywords\":[\"Digital Marketing\",\"Looker Studio\",\"SEO\",\"Tutorial\",\"Web Analytics\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/\",\"name\":\"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png\",\"datePublished\":\"2026-08-30T06:09:00+00:00\",\"description\":\"Getting more rows out of Search Console, splitting queries into clusters with regex fields, and reading what the data cannot say about AI results.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/08\\\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png\",\"width\":1200,\"height\":630,\"caption\":\"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/en\\\/digital-marketing\\\/tutorials-en-digital-marketing\\\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"luky\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"luky\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"],\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/author\\\/luky\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API - Lukas Wojcik - Blog","description":"Getting more rows out of Search Console, splitting queries into clusters with regex fields, and reading what the data cannot say about AI results.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/","og_locale":"en_US","og_type":"article","og_title":"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API - Lukas Wojcik - Blog","og_description":"Getting more rows out of Search Console, splitting queries into clusters with regex fields, and reading what the data cannot say about AI results.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/","og_site_name":"Lukas Wojcik - Blog","article_published_time":"2026-08-30T06:09:00+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png","type":"image\/png"}],"author":"luky","twitter_card":"summary_large_image","twitter_misc":{"Written by":"luky","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/#article","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/"},"author":{"name":"luky","@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"headline":"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API","datePublished":"2026-08-30T06:09:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/"},"wordCount":915,"commentCount":0,"publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png","keywords":["Digital Marketing","Looker Studio","SEO","Tutorial","Web Analytics"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/","url":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/","name":"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/#primaryimage"},"image":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/#primaryimage"},"thumbnailUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png","datePublished":"2026-08-30T06:09:00+00:00","description":"Getting more rows out of Search Console, splitting queries into clusters with regex fields, and reading what the data cannot say about AI results.","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/#primaryimage","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/hero-10146-tutorial-building-an-seo-and-geo-vis-c.png","width":1200,"height":630,"caption":"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API"},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/en\/digital-marketing\/tutorials-en-digital-marketing\/tutorial-building-an-seo-and-geo-visibility-dashboard-on-the-search-console-api\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Tutorial: Building an SEO and GEO Visibility Dashboard on the Search Console API"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"luky","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"luky"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"],"url":"https:\/\/www.lukaswojcik.com\/blog\/author\/luky\/"}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/10146","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=10146"}],"version-history":[{"count":3,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/10146\/revisions"}],"predecessor-version":[{"id":12314,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/posts\/10146\/revisions\/12314"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media\/11407"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=10146"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/categories?post=10146"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=10146"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}