Agentic Platform
Documentation API reference Tools Skills

Data

Botify Graph

Every Botify product writes its data to the same place: crawls, server logs, Search Console, analytics, AI visibility, SpeedWorkers, PageWorkers, product feeds. The Botify Graph exposes all of it for a project as plain SQL tables, under one catalog. namespace, so a single query can join a crawl to its logs and its search traffic.

How it works

The Graph is read through the tables_* tools, which are regular tools: call them over MCP or over the API, with an organization and a project like any other. Queries are written in BigQuery Standard SQL and every table is addressed as catalog.<table>.

Table names are stable aliases you can read and type: the crawl of 13 July 2026 is catalog.crawl_pages_20260713, Google bot hits are catalog.logs_google_crawls. The tools map them to the physical storage and check that you have access to the project.

tables_list    →  which tables does this project have?
tables_schema  →  which columns does this table have?
tables_query   →  run the SQL

Product families

Tables come in families, one per product. Which ones exist depends on the products the project has enabled: tables_list is always the source of truth.

SiteCrawler

One set of tables per crawl, named after the crawl date.

TableOne row per
crawl_pages_<crawl>URL crawled: status, indexability, depth, inlinks, content, segments…
crawl_links_internal_<crawl>Internal link (source → destination, anchor, follow).
crawl_links_external_<crawl>Outgoing link to another domain.
crawl_resources_<crawl>Resource fetched while rendering (JS, CSS, images…).
crawl_structured_offer_<crawl>, structured_*Structured data object extracted from a page (offers, books, events, job postings).

The two most recent crawls are also listed as crawl_pages_latest and crawl_pages_previous (same for every crawl table), which is the easiest way to compare one crawl to the next.

LogAnalyzer

Server logs, split per search engine and per month. The engine is one of google, bing, yandex, naver, baidu, apple, openai and other_ai_bots (Anthropic, Perplexity, Meta, Mistral…).

TableOne row per
logs_<engine>_crawlsBot hit on the site.
logs_<engine>_visitsVisit referred by that engine.
logs_urlsURL seen in the logs: maps url_hash to the URL, to filter or join on URLs.
logs_urls_segmentsURL with its segments.
logs_segmented_metrics_<engine>Daily hits, visits and distinct URLs, pre-aggregated by segment.

Search Console (RealKeywords)

TableOne row per
search_consoleURL × keyword × device × country × day: clicks, impressions, position.
search_console_by_propertySame, aggregated at the property level.
search_console_first_seenURL, with the day it first appeared in Search Console.
search_console_keywords_groups, search_console_by_property_keywords_groupsKeyword hash, with the keyword groups it belongs to.

Analytics and Core Web Vitals

TableSource
visits_ga4, visits_conversions_ga4, paid_search_ga4, users_pageviewsGoogle Analytics 4
visits_adobeAdobe
visits_atinternetPiano (AT Internet)
visits_conversionAdobe and Piano conversions
core_web_vitalsCrUX field data, by URL, day and device

AI Visibility

TableOne row per
ai_visibility_resultsAnswer of an AI engine to a tracked prompt, with the brands it mentions and the domains it cites (nested arrays).
ai_visibility_prompts_blocklistPrompt excluded from the campaigns.

SpeedWorkers and PageWorkers

TableOne row per
speedworkers_served_pagesPage request handled by SpeedWorkers: bot, what was delivered, or why not.
speedworkers_indexed_pagesPage in the SpeedWorkers inventory, with its rendering and quality-control status.
pageworkers_served_pagesPage request on which PageWorkers optimizations were applied.

AgenticCatalog

TableOne row per
agentic_catalog_source_<source>_v<n>Product of a source's feed as it arrived, before normalization. One table per source and per pull: the highest version is the latest pull.
agentic_catalog_destinations_pushProduct delivered to a destination (OpenAI, Google Merchant Center), per push.
google_merchant_center_product_performanceGoogle Merchant Center impressions and clicks of a product, loaded daily.

The push table mixes every source and destination of the project: always filter on source_id and destination.

Other

TableContent
sitemapURLs added, changed or removed in the sitemaps, run after run.
semrush_domain_organicSemrush organic keywords by domain.
Your own tablesAnything you created (see below).

The tools

ToolUse it to
tables_listList the table families of the project, with their dates. Takes optional plain-word filters such as "logs tables in 2026". Start here.
tables_schemaGet the columns of one table, with types, descriptions and enum values. Takes the bare name, without catalog..
tables_queryRun one SQL query and get the rows back (up to 10,000).
tables_query_exportRun a SELECT and export the full result as a CSV or Parquet file.
tables_text_to_sqlTurn a question in plain words into a SQL query against the project's tables.
tables_create, tables_insert, tables_loadCreate a table of your own and add rows to it, or create one from a CSV file.

Run a query

With the Botify MCP installed, just ask. The model lists the tables, reads their schemas and writes the SQL.

On my-org/my-project, how many compliant URLs of the latest crawl
were never crawled by Googlebot last month? Break it down by segment.

The botify-tables-sql skill teaches the model the conventions below and ships ready-made audit queries.

Rules of the road

Prefix every table with catalog.

FROM catalog.crawl_pages_20260713, not FROM crawl_pages_20260713. A table that does not exist fails the query rather than returning no rows: check its name with tables_list. INFORMATION_SCHEMA is not available; use tables_schema instead.

Bound the tables that grow forever

Logs, Search Console, analytics, served pages, sitemaps, segmented log metrics, the AgenticCatalog push table and Merchant Center performance keep growing day after day. tables_list gives each of them a time_filter column, with the first and last days with data when known, and tables_query rejects a query that reads one without bounding that column in the WHERE clause of the SELECT reading it.

SELECT keyword, SUM(clicks) AS clicks
FROM catalog.search_console
WHERE date >= '2026-09-01'
GROUP BY keyword
ORDER BY clicks DESC

Log tables are stored month by month: their filter on ts selects the months read, so it must bound ts from below with constant values (DATE(ts) BETWEEN '2026-09-01' AND '2026-09-30').

Join on url_hash

Crawl, logs, logs_urls and PageWorkers tables share the same 64-bit url_hash, which is the cheapest way to join them. The logs crawls and visits tables have a virtual url column you can select, group by or count; to filter, sort or join on URLs, join logs_urls on url_hash instead. SpeedWorkers is the exception: its urlHash is a different hash, so join on its urlFnv64Hash column instead. Search Console tables join on url.

-- Compliant pages of the latest crawl that Googlebot never visited in September
SELECT c.url, c.depth
FROM catalog.crawl_pages_latest AS c
LEFT JOIN (
  SELECT DISTINCT url_hash
  FROM catalog.logs_google_crawls
  WHERE DATE(ts) BETWEEN '2026-09-01' AND '2026-09-30'
) AS g USING (url_hash)
WHERE c.compliant__is_compliant AND g.url_hash IS NULL
ORDER BY c.depth

Read enums from the schema

Many integer columns (bot_id, delivery reasons, devices…) are enums. tables_schema lists their values, and most come with a readable *_name column next to them (bot_name, botName…): filter on the id, display the name. Columns flagged as bitmasks are tested with col & flag != 0. Bot ids of the logs and of SpeedWorkers are two different catalogs: compare bot names, never ids, across the two.

Mind the cost

Queries are billed in credits from the data they process: select the columns you need, filter on dates, and set max_results to what you will actually read. When Botify has set up a GCP project for your organization, tables_query can run there instead, and Google bills the scan directly.

Create your own tables

Derived datasets — a list of orphan pages, LLM-enriched product data, a keyword mapping — can be saved next to Botify's tables and queried the same way, as catalog.<your_table>. Botify's own tables are read-only.

Go further