跳到正文
DEV Community· Akshat Gupta·· 3 小時前AI 評分46

Cognee 如何透過 Google Search Console 連接器,為 AI 助理建立不過時的搜尋流量記憶

Giving an AI assistant a memory of your Google search traffic that does not go stale

AI 導讀

作者為 Cognee 開發 Google Search Console 連接器,按月整理搜尋流量資料,並重新讀取尚未定稿的月份,避免知識圖譜沿用過時數據。連接器只讀取 Google 的最終數據,已關閉的月份不會再次讀取;110 項測試在 Python 3.10、3.12 及 Cognee 1.6.4、1.6.6 通過。作者以真實帳戶測試時,因網站過去 80 天沒有搜尋流量,未建立文件。

正文

Picture this.

You ask your AI assistant which pages bring in the most search traffic. It answers with confidence. The numbers are from three months ago, for a site you stopped managing in August.

Nothing crashed. The assistant just kept a memory of data that is no longer true.

I wanted a memory of Google search traffic that stays current, and that forgets what it should. So for Mergetober I built a Google Search Console connector for Cognee. The work is for issue #4793.

What it does

Cognee turns documents into a knowledge graph that an agent can search. The connector feeds it from Search Console. You sign in with Google, pick your properties, and it syncs how they perform in search.

Search Console gives you numbers, not prose. One row per date, query and page would be millions of documents, and an LLM would read every one. So the connector groups the data by calendar month. Each month of a property becomes:

  • an overview: totals, devices, top countries, top queries and top pages;
  • one document per top page, with the queries that led to it.

All of a property's documents share one node set. The same query in two months becomes one entity in the graph, so you can ask how it changed.

source = google_search_console_source(
    sites=["sc-domain:example.com"],  # leave it out for every verified property
    months=3,
)
await cognee.remember(source, dataset_name="search_console",
                      primary_key="id", write_disposition="merge")

Sign-in is OAuth 2.0 with the read-only scope. Run login.py once, in the browser, and the token is cached in a private file.

Data that is late and sampled

Two things make Search Console different from a normal source.

First, the newest data is late and preliminary. Google publishes final numbers about two days behind, and it can still revise the last days. So the connector reads final data only. A month stays open until it is a few days older than that lag. An open month is read again on every run. Then it is read one last time and closed, and a closed month is never read again. Only documents whose text changed are sent on, so an unchanged run makes no LLM call.

Second, the data is sampled. Google returns the top rows by clicks and leaves out rare queries for privacy. That means a query that disappears from a response is not a deleted query, and the rows never add up to the totals. Every document says so.

What gets forgotten

A property you remove, deselect, or lose verification on is forgotten whole, with its documents. I added a few safety rules, because a wrong delete is worse than a missed one:

  • A failed request never deletes anything. The run stops and the next one starts from the same spot.
  • A month that suddenly comes back empty keeps its documents. Google having a bad moment is more likely than every click vanishing.
  • If Google throttles the sync, it stops cleanly and keeps the months it already read. It waits a minute at most at a time, because a sync holds Cognee's lock. The next run picks up where it stopped.
  • If the account suddenly sees no verified property, the run stops instead of forgetting everything.

The real test

First I tested against a fake: an in-memory copy of the Search Console API. It aggregates real fact rows, sorts by clicks, hides the newest days, and withholds rare queries. 110 tests pass on Python 3.10 and 3.12, and on Cognee 1.6.4 and 1.6.6. They include a run of the whole Cognee pipeline with a mocked LLM. The 106 that skip that pipeline run also pass on Python 3.14. But a fake only proves what you thought to fake.

So I signed in with a real Google account. I created an OAuth client, went through the browser consent, and listed my properties. Google returned my one property, with siteOwner permission. I then ran the connector against it twice.

Here is the honest part. My only property is a personal portfolio, and it had no search traffic in the last 80 days. So the real sync found no data. It created no documents and raised no errors. The second run skipped the two closed months:

run 1  {'sites': 1, 'periods': 3, 'closed': 0, 'documents': 0, ...}
run 2  {'sites': 1, 'periods': 1, 'closed': 2, 'documents': 0, ...}

The bug only a real Google could find

That empty property showed me something my fake got wrong.

When there is no data, I expected Google to answer with an empty response. It does not. For a query with no dimensions, it returns one row of zeros: {'clicks': 0, 'impressions': 0, ...}.

My code read "one row" as "there is data". It would have written an overview that says "0 clicks" for every empty month. Worse, it would have walked straight past my own safety rule. A month that had real documents and then got a zero row back would have been overwritten with zeros, instead of being kept.

Now a row with zero impressions counts as no data. I changed the fake to behave the way Google does, so a test fails if this comes back.

The same run settled a smaller question. Google accepts the lowercase type and dataState values that I send.

What I did not test

I did not test any of this against real traffic: documents built from real queries and pages, a recall on real data, a changed month, or forgetting a real property. Those paths are covered by the fake-API tests and the mocked-LLM pipeline test, not by a live account. I also never saw a real 429 from Google.

Rare queries are left out of the lists by design. A long tail of low-click pages shows up in the totals only. Sitemaps and URL inspection are not ingested. The README lists these.

Try it

The example is in packages/connector/google-search-console/examples/. You need a Google Cloud project with the Search Console API enabled, an OAuth client of type Desktop app, and a verified property. The README walks through it.

If you point it at a property with real traffic, I would love to hear what breaks.

來源:DEV Community · dev.to