AutoPodAutoPod

Tehisintellekti viidete mõju mõõtmine: analüütika, logid ja paneelide kraapimine

•21 min lugemist
Audioartikkel
Tehisintellekti viidete mõju mõõtmine: analüütika, logid ja paneelide kraapimine
0:00—:—
Tehisintellekti viidete mõju mõõtmine: analüütika, logid ja paneelide kraapimine

Tehisintellekti viidete mõju mõõtmine: analüütika, logid ja paneelide kraapimine

Sissejuhatus

AI-põhine avastamine jaguneb nüüd mitme mõõtmiskihiga. Inimene võib näha ettevõtet viidatuna tehisintellekti vastuses, klõpsata lingil ilma kasuliku viitajateta, külastada brauseri kaudu, mis eemaldab kampaaniaandmed, või lugeda vastust üldse klikkimata. Samal ajal võib tehisintellekti roomaja küsida ettevõtte lehekülge ilma inimkülastajat esindamata.

Seega peab kasulik mõõtmissüsteem eraldama neli küsimust:

  1. Kas saiti roomati või hangiti?
  2. Kas saiti viidati tehisintellekti vastuses?
  3. Kas inimene külastas saiti sellest vastusest?
  4. Kas see külastus tõi kaasa sisulise kaasatuse või tulu?

Alates 22. septembrist 2026 on esimese osapoole aruandlus paranemas. Google Search Console pakub generatiivse tehisintellekti jõudluse aruannet AI ülevaadete ja AI režiimi kohta, hõlmates näitamisi, lehekülgi, riike, seadmeid ja kuupäevi. Aruanne sai ülemaailmselt kättesaadavaks 31. augustil 2026. Google'i generatiivse tehisintellekti jõudluse aruanne (support.google.com)

Microsoft pakub ka tehisintellekti jõudluse aruannet Bing Webmaster Tools'is. Selle avalik eelvaade annab aruannet viidete koguarvu, viidatud lehekülgede, alusküsimuste ja viidete trendide kohta toetatud Microsofti tehisintellekti kogemustes. Bing Webmaster Tools'i tehisintellekti jõudlus (blogs.bing.com)

Neid tööriistu tuleks pidada autoriteetseteks oma platvormide jaoks, kuid need ei loo terviklikku abistajateülest mõõtmissüsteemi. Soovitatav lähenemine on kombineerida esimese osapoole aruanded, serverilogid, kontrollitud jälgimislingid, analüütika ekspordid ja ajastatud vastuspaneeli vaatlused.


1. Miks tehisintellekti suunamiste mõõtmine on keeruline

Traditsiooniline veebianalüütika sõltub suuresti Referer päisest ja kampaania parameetritest. Mõlemad võivad puududa või olla mittetäielikud.

HTTP Referer päis võib sisaldada eelmist lehekülge, ainult eelmise veebisaidi päritolu või üldse mitte mingit väärtust. Brauseri viitaja poliitikad võivad seda teavet tahtlikult piirata või eemaldada. MDN Referrer-Policy dokumentatsioon (developer.mozilla.org)

Tehisintellekti süsteemid loovad täiendavaid keerukusi:

  • Abistaja võib linkida lehele ilma äratuntavat viitajat saatmata.
  • Abistaja võib kasutada ümbersuunavat või ümberkirjutatud URL-i.
  • Abistaja võib sisu serveri poolel enne vastuse näitamist alla laadida.
  • Tehisintellekti roomaja võib külastada lehte ilma, et inimene seda näeks.
  • Vastus võib viidata kanoonilisele URL-ile algselt hangitud URL-i asemel.
  • Vastus võib muutuda sõltuvalt asukohast, seadmest, keelest, ajast või isikupärastamisest.

Näiteks eristab OpenAI OAI-SearchBot'i otsingu avastamiseks, GPTBot'i võimaliku treeningkasutuse jaoks ja ChatGPT-User'i kasutaja algatatud tegevuste jaoks. Perplexity eristab eraldi PerplexityBot'i ja Perplexity-User'i. Anthropic eristab ClaudeBot'i, Claude-SearchBot'i ja Claude-User'i. Neid päringuid ei tohiks kombineerida üheks üldiseks “AI liikluse” numbriks. OpenAI roomaja dokumentatsioon (openai.com) Perplexity roomaja dokumentatsioon (docs.perplexity.ai) Anthropic roomaja dokumentatsioon (support.anthropic.com)

Keskne reegel on:

Roomaja tegevus ei ole suunav liiklus, viidete nähtavus ei ole liiklus ja liiklus ei ole äritegevuse mõju.


2. Mõõtmisraamistik

Kasutage viit mõõtmiskihti.

KihtPeamine küsimusSoovitatavad andmed
JuurdepääsKas tehisintellekti süsteem küsis lehte?Veebiserveri logid, tulemüüri logid
NähtavusKas lehte näidati või viidati?Google Search Console, Bing Webmaster Tools, vastuspaneeli vaatlused
OmandamineKas inimene saabus tehisintellekti platvormilt?Viitaja, kampaania parameetrid, lühilingi klikid, analüütika
KaasamineKas külastaja suhtles sisukalt?Analüütika sündmused, lehevaatamised, kaasamise aeg
VäärtusKas külastus tõi soovitud tulemuse?Registreerumised, müügivihjed, ostud, tellimused

Soovitatav tõeallika hierarhia

Kasutage iga küsimuse jaoks tugevaimat saadaolevat signaali:

  1. Esimese osapoole platvormi aruanded näitamiste ja viidete kohta.
  2. Vastuspaneeli vaatlused päringutaseme nähtavuse ja konkurentsivõrdluste jaoks.
  3. Ümbersuunamislogid kontrollitud lingiklikkide jaoks.
  4. Veebianalüütika seansside, kaasamise ja konversioonide jaoks.
  5. Serverilogid roomaja ja sisu laadimise tegevuse kohta.
  6. Modelleeritud hinnangud ainult siis, kui otseseid tõendeid pole saadaval.

Ärge kombineerige kõiki signaale ühte numbriks ilma allikat ja usaldusväärsuse taset säilitamata.


3. Põhiandmemudel

Looge andmeladu eraldi tabelitega toorvaatluste ja tuletatud mõõdikute jaoks.

panel_runs

Üks rida iga päringu ja platvormi kontrolli kohta.

text run_id observed_at surface topic prompt_id query_text locale country device panel_present panel_type answer_hash raw_html_path screenshot_path collector_version status

panel_citations

Üks rida iga vastuspaneelis vaadeldud lingi kohta.

text run_id surface topic prompt_id cited_url cited_domain citation_position link_scope target_domain target_cited

ai_crawler_requests

Agregeeritud serverilogide andmed.

text date bot_name bot_role path requests successful_requests error_requests unique_ip_count

shortener_clicks

Üks rida iga kontrollitud lingipäringu kohta.

text click_id occurred_at slug surface topic prompt_id asset_id referrer_host user_agent_family ip_hmac destination_path

ai_sessions

Normaliseeritud analüütika tabel.

text session_id date surface topic prompt_id landing_page attribution_method confidence engaged engagement_time_seconds key_event revenue

Väli confidence on oluline. Soovitatavad väärtused on:

  • A — Otse: kontrollitud lühilingi klikk või usaldusväärne kampaania parameeter.
  • B — Tugev: tuntud abistaja viitaja või kinnitatud kasutaja-saatmise päring.
  • C — Tõenäoline: kampaania või sihtlehe tõend ilma täieliku viitajata.
  • D — Modelleeritud: tuletatud ajastuse, paneeli vaatluste või koondmuutuste põhjal.

Aruandlus A ja B eraldi C-st ja D-st.


4. Mõõdikute definitsioonid

Viidete osakaal teema järgi

Viidete osakaal teema järgi mõõdab, kui tihti sihtdomeen esineb teema kohta vaadeldud allikate hulgas.

\[ \text{Viidete osakaal}_{teema}

\frac{\text{Sihtdomeeni viidete esinemised}} {\text{Kõik viidete esinemised}} \]

Näide:

  • 100 viidet kokku täheldati teema “projektijuhtimistarkvara” kohta
  • 12 viidet viitavad teie domeenile
  • Viidete osakaal teema järgi = 12%

See mõõdik mõõdab allika osakaalu, mitte seda, kas vastus sisaldas teie saiti vähemalt korra.

Viidete katvus

Kasutage teist mõõdikut vastuse tasandi olemasolu jaoks:

\[ \text{Viidete katvus}_{teema}

\frac{\text{Vastuse käivitused, mis sisaldavad sihtviidet}} {\text{Vastuse käivitused, kus paneel oli kohal}} \]

Viidete katvust on mittetehnilistel auditooriumidel sageli lihtsam mõista:

"Meie sait ilmus 34% teema kohta vaadeldud tehisintellekti vastustest."

Viite positsioon

Salvestage viite positsioon vastuses:

  • 1 = esimene täheldatud allikas
  • 2 = teine täheldatud allikas
  • 3 = kolmas täheldatud allikas

Kuna tehisintellekti liidesed sageli rühmitavad või järjestavad allikaid ümber, käsitlege positsiooni kirjeldava vaatlusena, mitte universaalse järjestusena.


Abistaja suunamismäär

Abistaja suunamismäär mõõdab inimeste veebisaidi seansside osakaalu, mida saab omistada tehisintellekti platvormile.

\[ \text{Abistaja suunamismäär}

\frac{\text{AI-le omistatud inimeste seansid}} {\text{Kõik inimeste seansid}} \]

Esitage vähemalt kaks versiooni:

text Kinnitatud abistaja suunamismäär = A-usaldusväärsusega AI seansid / kõik inimeste seansid

Laiendatud abistaja suunamismäär = A + B + C-usaldusväärsusega AI seansid / kõik inimeste seansid

Kinnitatud versioon on konservatiivsem. Laiendatud versioon on kasulik trendianalüüsiks, kuid seda ei tohiks esitada kui täielikult vaadeldud liiklust.

Ärge kasutage paneeli käivitusi näitamistena

Kui kraabite 500 päringut, ei tähenda see, et 500 inimest neid vastuseid nägi. Teie kraapija mõõdab kontrollitud valimit vastuse olekutest. Kasutage esimese osapoole platvormi näitamisarvude aruandeid, kui need on saadaval.


Viitejärgne kaasamine

Viitejärgne kaasamine mõõdab, kas tehisintellekti viite kaudu saabunud inimesed sooritasid sisuka tegevuse.

\[ \text{Viitejärgne kaasamine}

\frac{\text{Kaasatud AI seansid}} {\text{AI-le omistatud seansid}} \]

Google Analytics 4 puhul kestab kaasatud seanss üle 10 sekundi, sisaldab olulist sündmust või sisaldab vähemalt kahte lehe- või ekraanivaatamist. Google Analyticsi kaasamise määra dokumentatsioon (support.google.com)

Aruandluses esitage ka:

text Viitejärgne kaasamise aeg = keskmine kaasamise aeg sekundites AI seansi kohta

Viitejärgne konversioonimäär = AI seansid olulise sündmusega / AI-le omistatud seansid

Viitejärgne tulu seansi kohta = tulu AI seanssidest / AI-le omistatud seansid

Keskmine kaasamise aeg on tavaliselt stabiilsem kui keskmine kaasamise aeg, kuna väike arv väga pikki seansse võib keskmist moonutada.


Täiendavad kasulikud mõõdikud

AI roomaja edukuse määr

\[ \text{Roomaja edukuse määr}

\frac{\text{AI roomaja päringud, mis tagastavad 2xx või 3xx}} {\text{AI roomaja päringud}} \]

Jagage see roomajate ja teede kaupa. Suur viidete langus koos kasvava roomajate veamääraga võib viidata hostingu, tulemüüri või robotite konfiguratsiooniprobleemile.

Viite-kliki määr

Kontrollitud vastuspaneeli vaatluste puhul:

\[ \text{Vaadeldud viite-kliki määr}

\frac{\text{Kinnitatud lühilingi klikid}} {\text{Vaadeldud sihtviited}} \]

See ei ole tõeline kasutaja klikimismäär, välja arvatud juhul, kui nimetaja esindab tegelikke kasutaja näitamisi. Märgistage see selgelt kui vaadeldud operatiivne mõõdik.

Viite värskus

Mõõtke, kui tihti viidatud URL peegeldab lehe praegust versiooni.

text Viite värskus = viidatud lehed praeguse sisu räsiga / viidatud lehed

See on kasulik dokumentatsiooni-, hinnakujunduse-, toote- ja poliitikalehtede puhul, mis sageli muutuvad.


5. Serverilogide analüüs

Konfigureerige struktureeritud juurdepääsulogid

Struktureeritud logid on lihtsamini analüüsitavad kui traditsioonilised tühikutega eraldatud logid.

Nginxi konfiguratsiooni näide:

nginx log_format ai_json escape=json '{' '"ts":"$time_iso8601",' '"remote_addr":"$remote_addr",' '"request":"$request",' '"status":$status,' '"bytes":$body_bytes_sent,' '"referer":"$http_referer",' '"user_agent":"$http_user_agent",' '"host":"$host"' '}';

access_log /var/log/nginx/ai-access.jsonl ai_json;

Salvestage logifailid piiratud asukohta. Ärge saatke töötlemata IP-aadresse üldisesse analüütikatabelisse, välja arvatud juhul, kui teil on selge operatiivne põhjus.

Tehiseintellekti päringute tüüpide tuvastamine

Vähemalt eraldage:

text OpenAI:

  • OAI-SearchBot
  • ChatGPT-User
  • GPTBot

Anthropic:

  • Claude-SearchBot
  • Claude-User
  • ClaudeBot

Perplexity:

  • PerplexityBot
  • Perplexity-User

Otsingumootorid:

  • Googlebot
  • Bingbot

Google'i AI otsingufunktsioonid kasutavad üldiselt olemasolevaid Google Searchi roomamise kontrolle, mitte eraldi universaalset “AI Overview bot'i”. Google teatab, et Googlebot kontrollib otsingule juurdepääsu, sealhulgas AI funktsioone. Google'i AI funktsioonid ja veebisaidid (developers.google.com)

User-agent stringe saab võltsida. Operatiivsete otsuste jaoks kombineerige user-agent vastavust pakkuja avaldatud IP-vahemikega või kinnitatud pöörd-DNS-iga, kui see on saadaval. OpenAI ja Perplexity avaldavad oma asjakohaste roomajate ja hangitavate kohta IP-teavet. (openai.com)

Korratav logikokkuvõtja

Salvestage järgmine kui ai_log_summary.py.

python #!/usr/bin/env python3

import csv import hashlib import hmac import json import os import re import sys from collections import Counter, defaultdict from datetime import datetime from urllib.parse import urlsplit

BOT_PATTERNS = { "OAI-SearchBot": ("openai", re.compile(r"\bOAI-SearchBot\b", re.I)), "ChatGPT-User": ("openai_user", re.compile(r"\bChatGPT-User\b", re.I)), "GPTBot": ("openai_training", re.compile(r"\bGPTBot\b", re.I)), "Claude-SearchBot": ("anthropic", re.compile(r"\bClaude-SearchBot\b", re.I)), "Claude-User": ("anthropic_user", re.compile(r"\bClaude-User\b", re.I)), "ClaudeBot": ("anthropic_training", re.compile(r"\bClaudeBot\b", re.I)), "PerplexityBot": ("perplexity", re.compile(r"\bPerplexityBot\b", re.I)), "Perplexity-User": ("perplexity_user", re.compile(r"\bPerplexity-User\b", re.I)), "Googlebot": ("google_search", re.compile(r"\bGooglebot\b", re.I)), "Bingbot": ("bing_search", re.compile(r"\bbingbot\b", re.I)), }

SECRET = os.environ.get("HMAC_SECRET", "replace-this-in-production").encode()

def hmac_ip(ip): return hmac.new(SECRET, ip.encode(), hashlib.sha256).hexdigest()[:16]

def classify_bot(user_agent): for bot_name, (role, pattern) in BOT_PATTERNS.items(): if pattern.search(user_agent or ""): return bot_name, role return None, None

def parse_path(request_line): try: parts = request_line.split() return urlsplit(parts[1]).path except Exception: return "/"

def main(input_path): totals = defaultdict(lambda: { "requests": 0, "success": 0, "errors": 0, "ips": set(), "paths": Counter(), })

with open(input_path, "r", encoding="utf-8") as source:
    for line in source:
        try:
            record = json.loads(line)
        except json.JSONDecodeError:
            continue

        bot_name, bot_role = classify_bot(record.get("user_agent", ""))
        if not bot_name:
            continue

        timestamp = record.get("ts", "")
        date = datetime.fromisoformat(
            timestamp.replace("Z", "+00:00")
        ).date().isoformat()

        status = int(record.get("status", 0))
        path = parse_path(record.get("request", ""))
        key = (date, bot_name, bot_role)

        totals[key]["requests"] += 1
        totals[key]["ips"].add(hmac_ip(record.get("remote_addr", "")))
        totals[key]["paths"][path] += 1

        if 200 <= status < 400:
            totals[key]["success"] += 1
        else:
            totals[key]["errors"] += 1

writer = csv.writer(sys.stdout)
writer.writerow([
    "date",
    "bot_name",
    "bot_role",
    "requests",
    "successful_requests",
    "error_requests",
    "unique_ip_count",
    "top_paths",
])

for (date, bot_name, bot_role), values in sorted(totals.items()):
    top_paths = values["paths"].most_common(10)
    writer.writerow([
        date,
        bot_name,
        bot_role,
        values["requests"],
        values["success"],
        values["errors"],
        len(values["ips"]),
        json.dumps(top_paths),
    ])

if name == "main": if len(sys.argv) != 2: print("Usage: python ai_log_summary.py /path/to/access.jsonl") sys.exit(1)

main(sys.argv[1])

Käivitage see järgmiselt:

bash HMAC_SECRET='a-long-random-secret' \ python ai_log_summary.py /var/log/nginx/ai-access.jsonl \

data/ai_crawler_daily.csv

See annab operatiivseid tõendeid sisu hankimise tegevuse, mitte inimliikluse kohta.


6. Kohandatud lingilühendajad tehisintellektile suunatud kokkuvõtete jaoks

Esimese osapoole lingilühendaja pakub kontrollitud mõõtepunkti, kui avaldate kokkuvõtteid või lähtematerjale, millele tehisintellekti süsteemid võivad viidata.

Kasutage domeeni, mida te kontrollite, näiteks:

text https://go.example.com/ai-docs

Sihtkohas peaksid olema kampaania parameetrid, näiteks:

text utm_source=perplexity utm_medium=ai_answer utm_campaign=product_documentation utm_content=pricing_summary_v3

Google soovitab kasutada kampaania parameetreid liikluse allikate ja kampaaniate tuvastamiseks. Google Analyticsi kampaania URL-i dokumentatsioon (support.google.com)

Soovitatavad lingiväljad

text surface topic prompt_id asset_id content_version destination_path

Ärge lisage linki isiklikke andmeid, e-posti aadresse ega kasutaja otsingupäringuid. Kampaania identifikaatorid peaksid kirjeldama avaldatud vara, mitte identifitseerima isikut.

Olulised piirangud

Lühilink on kalibreerimisseade, mitte universaalne lahendus:

  • Abistaja võib siht-URL-i ümber kirjutada.
  • Abistaja võib selle asemel viidata kanoonilisele URL-ile.
  • Link võidakse kuvada, kuid seda ei klõpsata kunagi.
  • Brauser või privaatsustööriist võib viitaja eemaldada.
  • Mõned süsteemid võivad sihtkoha serveri poolel alla laadida.
  • Lühilink ei mõõda kasutajaid, kes mäletavad brändi ja naasevad hiljem.

Ärge kasutage lühendajat sihtkoha peitmiseks, turvasüsteemidest möödahiilimiseks ega viidete manipuleerimiseks. Kasutage selget ümbersuunamist asjakohasele, kanoonilisele lehele.

Minimaalne esimese osapoole lühendaja

Järgmine näide kasutab FastAPI-t ja SQLite-i. Enne tootmises kasutamist kaitske lingi loomise lõpp-punkt autentimisega.

python

shortener.py

import hashlib import hmac import os import secrets import sqlite3 from datetime import datetime, timezone from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit

from fastapi import FastAPI, HTTPException, Request from fastapi.responses import RedirectResponse from pydantic import BaseModel

DB_PATH = os.environ.get("SHORTENER_DB", "shortener.db") HMAC_SECRET = os.environ.get( "HMAC_SECRET", "replace-this-in-production" ).encode()

ALLOWED_HOST = "www.example.com"

app = FastAPI()

def db(): connection = sqlite3.connect(DB_PATH) connection.row_factory = sqlite3.Row return connection

def init_db(): connection = db() connection.execute(""" CREATE TABLE IF NOT EXISTS links ( slug TEXT PRIMARY KEY, destination TEXT NOT NULL, surface TEXT NOT NULL, topic TEXT, prompt_id TEXT, asset_id TEXT, created_at TEXT NOT NULL ) """) connection.execute(""" CREATE TABLE IF NOT EXISTS clicks ( id INTEGER PRIMARY KEY AUTOINCREMENT, occurred_at TEXT NOT NULL, slug TEXT NOT NULL, surface TEXT, topic TEXT, prompt_id TEXT, referrer_host TEXT, user_agent TEXT, ip_hmac TEXT ) """) connection.commit() connection.close()

def append_query(url, params): parsed = urlsplit(url) query = dict(parse_qsl(parsed.query, keep_blank_values=True)) query.update(params) return urlunsplit(( parsed.scheme, parsed.netloc, parsed.path, urlencode(query), parsed.fragment, ))

def hash_ip(ip): return hmac.new( HMAC_SECRET, (ip or "").encode(), hashlib.sha256 ).hexdigest()[:16]

class LinkRequest(BaseModel): destination_path: str surface: str topic: str | None = None prompt_id: str | None = None asset_id: str | None = None

@app.on_event("startup") def startup(): init_db()

@app.post("/links") def create_link(payload: LinkRequest): destination = f"https://{ALLOWED_HOST}{payload.destination_path}"

if not payload.destination_path.startswith("/"):
    raise HTTPException(400, "destination_path must be a site-relative path")

slug = secrets.token_urlsafe(7).replace("_", "-").replace("/", "-")

target = append_query(destination, {
    "utm_source": payload.surface,
    "utm_medium": "ai_answer",
    "utm_campaign": "citation_measurement",
    "utm_content": payload.asset_id or "unspecified",
})

connection = db()
connection.execute("""
    INSERT INTO links
    (slug, destination, surface, topic, prompt_id, asset_id, created_at)
    VALUES (?, ?, ?, ?, ?, ?, ?)
""", (
    slug,
    target,
    payload.surface,
    payload.topic,
    payload.prompt_id,
    payload.asset_id,
    datetime.now(timezone.utc).isoformat(),
))
connection.commit()
connection.close()

return {"slug": slug, "url": f"https://go.example.com/{slug}"}

@app.get("/{slug}") def redirect(slug: str, request: Request): connection = db() row = connection.execute( "SELECT * FROM links WHERE slug = ?", (slug,) ).fetchone()

if not row:
    connection.close()
    raise HTTPException(404, "Unknown link")

referrer = request.headers.get("referer", "")
referrer_host = urlsplit(referrer).hostname or ""

connection.execute("""
    INSERT INTO clicks
    (occurred_at, slug, surface, topic, prompt_id,
     referrer_host, user_agent, ip_hmac)
    VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""", (
    datetime.now(timezone.utc).isoformat(),
    slug,
    row["surface"],
    row["topic"],
    row["prompt_id"],
    referrer_host,
    request.headers.get("user-agent", "")[:300],
    hash_ip(request.client.host if request.client else ""),
))
connection.commit()
connection.close()

return RedirectResponse(row["destination"], status_code=302)

Käivitage see järgmiselt:

bash pip install fastapi uvicorn uvicorn shortener:app --host 0.0.0.0 --port 8080

Kasutage mõõtmislinkide jaoks 302 ümbersuunamist, et brauserid ja vahesüsteemid püsivat ümbersuunamist püsivalt vähem tõenäoliselt vahemällu talletaksid.


7. Tehisintellekti vastuspaneelide ajastatud kraapimine

Paneelide kraapimine on kasulik küsimuste vastamiseks, mida esimese osapoole analüütika ei pruugi paljastada:

  • Milliseid konkureerivaid allikaid viidatakse?
  • Millist lehte viidatakse konkreetse päringu jaoks?
  • Kas vastus muutub riigi või seadme järgi?
  • Kas viide ilmub vastuses, allikate loendis või mõlemas?
  • Kui stabiilne on vastus aja jooksul?
  • Kas abistaja viitab lühilingile või kanoonilisele URL-ile?

Kraapimist tuleb aga teha hoolikalt.

Vastutustundliku kogumise reeglid

  1. Eelistage ametlikku API-t, litsentseeritud otsinguandmete pakkujat või esimese osapoole aruannet.
  2. Enne päringute automatiseerimist vaadake üle teenusepakkuja tingimused.
  3. Austage robotite juhiseid, kus see on kohaldatav.
  4. Ärge mööduge CAPTCHA-dest, sisselogimisbarjääridest, päringute piirangutest ega botikaitsetest.
  5. Kasutage väikest, fikseeritud päringute komplekti.
  6. Käivitage madala sagedusega.
  7. Salvestage vastus ja ajatempel, et tulemusi saaks auditeerida.
  8. Peatuge, kui teenusepakkuja tagastab väljakutse või juurdepääs keelatud vastuse.

Robotite välistamise protokoll on roomajate eelistuste mehhanism, mitte turvasüsteem. See ei luba juurdepääsu kaitstud sisule. RFC 9309: Robots Exclusion Protocol (rfc-editor.org)

Koostage päringute manifest

csv prompt_id,topic,query,locale,surface,target_domain pm_001,project-management,"best project management software for remote teams",en-US,google,example.com pm_001,project-management,"best project management software for remote teams",en-US,bing,example.com pm_002,analytics,"how to measure AI referral traffic",en-US,google,example.com

Hoidke päringud stabiilsena. Kui päringud muutuvad, muutuvad trendivõrdlused vähem usaldusväärseks.

Salvestage ka:

  • riik
  • keel
  • seadme tüüp
  • brauseri versioon
  • päringu versioon
  • sisu versioon
  • kogumisaeg UTC-s

Google märgib, et AI ülevaate ja AI režiimi vastused võivad varieeruda, kuna need kasutavad erinevaid süsteeme ja võivad kasutada seotud otsinguid või “päringu hargnemist”. Google'i AI funktsioonid ja veebisaidi dokumentatsioon (developers.google.com)

Playwrighti kogumisskript

Järgnev skript on üldotstarbeline uurimisrakendus. See salvestab renderdatud lehe, ekraanipildi, lehelingid ja vastuse teksti. See ei ürita tahtlikult väljakutsetest mööda minna ega juurdepääsukontrolle murda.

python

scrape_panels.py

import asyncio import csv import hashlib import json import os import re from datetime import datetime, timezone from pathlib import Path from urllib.parse import quote_plus, urljoin, urlsplit

from playwright.async_api import async_playwright

DATA_DIR = Path("data/panels") DATA_DIR.mkdir(parents=True, exist_ok=True)

SURFACE_URLS = { "google": "https://www.google.com/search?q={query}&hl=en&gl=us", "bing": "https://www.bing.com/search?q={query}&setlang=en-us", }

PANEL_MARKERS = { "google": ["AI Overview", "AI Mode"], "bing": ["Copilot", "Generative search"], }

BLOCK_MARKERS = [ "captcha", "unusual traffic", "verify you are human", "access denied", ]

def clean_text(value): return re.sub(r"\s+", " ", value or "").strip()

def host_matches(url, target_domain): host = (urlsplit(url).hostname or "").lower() target = target_domain.lower().lstrip("www.") return host == target or host.endswith("." + target)

def page_hash(text): normalized = clean_text(text).encode("utf-8") return hashlib.sha256(normalized).hexdigest()

async def collect_one(page, row): surface = row["surface"] query = row["query"] target_domain = row["target_domain"]

search_url = SURFACE_URLS[surface].format(
    query=quote_plus(query)
)

await page.goto(
    search_url,
    wait_until="domcontentloaded",
    timeout=45_000,
)
await page.wait_for_timeout(2500)

text = await page.locator("body").inner_text()
lowered = text.lower()

if any(marker in lowered for marker in BLOCK_MARKERS):
    return {
        **row,
        "observed_at": datetime.now(timezone.utc).isoformat(),
        "status": "blocked_or_challenged",
        "panel_present": False,
        "links": [],
    }

links = await page.locator("a").evaluate_all("""
    anchors => anchors.map(a => ({
        href: a.href || "",
        text: (a.innerText || "").trim()
    })).filter(x => x.href)
""")

panel_present = any(
    marker.lower() in lowered
    for marker in PANEL_MARKERS.get(surface, [])
)

observed_at = datetime.now(timezone.utc)
run_id = hashlib.sha256(
    f"{surface}|{row['prompt_id']}|{observed_at.isoformat()}".encode()
).hexdigest()[:20]

html_path = DATA_DIR / f"{run_id}.html"
screenshot_path = DATA_DIR / f"{run_id}.png"

await page.screenshot(path=str(screenshot_path), full_page=True)
html_path.write_text(await page.content(), encoding="utf-8")

output_links = []
for position, link in enumerate(links, start=1):
    output_links.append({
        "href": urljoin(search_url, link["href"]),
        "text": clean_text(link["text"])[:300],
        "position": position,
        "target_cited": host_matches(
            link["href"],
            target_domain
        ),
    })

return {
    **row,
    "run_id": run_id,
    "observed_at": observed_at.isoformat(),
    "status": "ok",
    "panel_present": panel_present,
    "answer_hash": page_hash(text),
    "answer_text": clean_text(text)[:50_000],
    "html_path": str(html_path),
    "screenshot_path": str(screenshot_path),
    "link_scope": "page_fallback",
    "links": output_links,
}

async def main(manifest_path): rows = [] with open(manifest_path, newline="", encoding="utf-8") as source: rows = list(csv.DictReader(source))

output_path = DATA_DIR / (
    datetime.now(timezone.utc).strftime("%Y-%m-%d") + ".jsonl"
)

async with async_playwright() as playwright:
    browser = await playwright.chromium.launch(headless=True)
    context = await browser.new_context(
        locale="en-US",
        timezone_id="UTC",
    )
    page = await context.new_page()

    with open(output_path, "w", encoding="utf-8") as output:
        for row in rows:
            try:
                result = await collect_one(page, row)
            except Exception as exc:
                result = {
                    **row,
                    "observed_at": datetime.now(timezone.utc).isoformat(),
                    "status": f"error:{type(exc).__name__}",
                    "panel_present": False,
                    "links": [],
                }

            output.write(json.dumps(result) + "\

") output.flush()

            # Keep request volume low.
            await asyncio.sleep(8)

    await browser.close()

if name == "main": asyncio.run(main("prompts.csv"))

Paigaldage ja käivitage:

bash pip install playwright playwright install chromium python scrape_panels.py

Ajastage see lukuga, et kaks käivitust ei kattuks:

cron 15 3 * * * flock -n /tmp/ai-panel.lock \ /usr/bin/python3 /opt/ai-measure/scrape_panels.py

Täpsuse parandamine pinnadapteritega

Varuskript salvestab leheküljetaseme lingid. See on kasulik avastamiseks, kuid võib sisaldada tavalisi otsingutulemuste linke. Tootmiskasutuseks:

  • Kasutage litsentseeritud vastuspaneeli API-t, kui see on saadaval.
  • Looge iga pinna jaoks eraldi valija adapter.
  • Salvestage valija versioon.
  • Salvestage toores HTML ja ekraanipilt.
  • Märgistage iga kirje link_scope = "panel_selector" või link_scope = "page_fallback" abil.

Arvutage viidete osakaalu ainult panel_selector andmete põhjal, kui suudate paneeli usaldusväärselt tuvastada. Hoidke varuvaatlused eraldi uurimuslikus aruandes.


8. Google Analyticsi ja BigQuery integreerimine

Google Analytics 4 saab eksportida toores sündmuseandmeid BigQuerysse. Igapäevased eksportimised pakuvad stabiilseid tabeleid nagu events_YYYYMMDD; voogedastuse eksportimised on kasulikud peaaegu reaalajas jälgimiseks, kuid võivad olla mittetäielikud kuni igapäevase tabeli lõplikuks valmimiseni. Google Analyticsi BigQuery eksport (support.google.com)

Lihtsustatud seansipäring võiks välja näha selline:

sql WITH page_events AS ( SELECT event_date, user_pseudo_id,

(
  SELECT value.int_value
  FROM UNNEST(event_params)
  WHERE key = 'ga_session_id'
) AS session_id,

(
  SELECT value.string_value
  FROM UNNEST(event_params)
  WHERE key = 'page_location'
) AS page_location,

(
  SELECT value.string_value
  FROM UNNEST(event_params)
  WHERE key = 'session_engaged'
) AS session_engaged,

event_name

FROM PROJECT.analytics_PROPERTY.events_* WHERE _TABLE_SUFFIX BETWEEN '20260901' AND '20260921' ),

session_rollup AS ( SELECT event_date, user_pseudo_id, session_id,

MAX(
  CASE
    WHEN REGEXP_CONTAINS(
      LOWER(page_location),
      r'[?&]utm_medium=ai_answer'
    )
    THEN 1 ELSE 0
  END
) AS ai_session,

MAX(
  CASE
    WHEN session_engaged = '1'
    THEN 1 ELSE 0
  END
) AS engaged_session,

MAX(
  CASE
    WHEN event_name IN ('purchase', 'generate_lead', 'sign_up')
    THEN 1 ELSE 0
  END
) AS key_event

FROM page_events GROUP BY event_date, user_pseudo_id, session_id )

SELECT event_date, COUNTIF(ai_session = 1) AS ai_sessions, COUNTIF(ai_session = 1 AND engaged_session = 1) AS engaged_ai_sessions, COUNTIF(ai_session = 1 AND key_event = 1) AS ai_key_events, SAFE_DIVIDE( COUNTIF(ai_session = 1 AND engaged_session = 1), COUNTIF(ai_session = 1) ) AS post_citation_engagement_rate FROM session_rollup GROUP BY event_date ORDER BY event_date;

Küpse implementatsiooni puhul lisage surface, topic ja prompt_id kampaania struktuuri või ühendage need lühendaja klikkide tabelist.

Ärge looge igale üksikule kasutajale või seansile kõrge kardinaalsusega analüütikadimõõdet. Google hoiatab, et liigsed kõrge kardinaalsusega kohandatud dimensioonid võivad aruandluse kvaliteeti vähendada. Google Analyticsi kohandatud dimensioonid ja mõõdikud (support.google.com)


9. Armatuurlaua disain

Praktiline armatuurlaud peaks sisaldama viit vaadet.

Juhtkonna kokkuvõte

Kuvage:

  • Viidete osakaal teema järgi
  • Viidete katvus teema järgi
  • Kinnitatud abistaja suunamismäär
  • Laiendatud abistaja suunamismäär
  • Viitejärgne kaasamine
  • AI roomaja edukuse määr
  • AI-le omistatud põhisündmused või tulu

Viidete osakaalu trend

Joongraafik:

text Kuupäev × Teema × Platvorm

Näidake mõlemat:

  • sihtdomeeni viidete esinemised
  • kõik täheldatud viidete esinemised

Abistaja liikluse lehter

text Vaadeldud viited ↓ Kontrollitud lingiklikid ↓ AI-le omistatud seansid ↓ Kaasatud AI seansid ↓ Põhisündmused

Iga etapp peaks näitama oma omistamise usaldusväärsust.

Roomaja seisund

Tabel roomajate kaupa:

text roomaja_nimi päringud edukad_päringud veamäär unikaalsete_IP-de_arv populaarsemad_teed

Teavita, kui:

  • veamäär ületab 2 protsenti
  • roomaja kaob ootamatult
  • varem ligipääsetav sisuosa tagastab 403 või 429
  • roomaja päringud koondavad soovimatule privaatsele teele

Sisu võimaluste tabel

Järjestage lehed ja teemad järgmiselt:

text kõrge viidete osakaal + madal suunamismäär kõrged näitamised + madal viidete katvus kõrge kaasamine + madal viidete nähtavus kõrged roomaja vead + kõrge äriline tähtsus

Need kombinatsioonid annavad tavaliselt paremaid otsuseid kui ainult liikluse mahu vaatlemine.

Minimaalne Streamlit armatuurlaud

Salvestage kui dashboard.py.

python import glob import json from pathlib import Path

import pandas as pd import streamlit as st

st.set_page_config( page_title="AI Citation Impact", layout="wide", )

@st.cache_data(ttl=300) def load_panel_rows(): rows = []

for filename in glob.glob("data/panels/*.jsonl"):
    with open(filename, encoding="utf-8") as source:
        for line in source:
            record = json.loads(line)

            run_id = record.get("run_id")
            for link in record.get("links", []):
                hostname = link.get("href", "").split("/")[2]
                rows.append({
                    "run_id": run_id,
                    "observed_at": record.get("observed_at"),
                    "surface": record.get("surface"),
                    "topic": record.get("topic"),
                    "prompt_id": record.get("prompt_id"),
                    "panel_present": record.get("panel_present"),
                    "target_domain": record.get("target_domain"),
                    "cited_domain": hostname,
                    "target_cited": link.get("target_cited", False),
                    "position": link.get("position"),
                    "link_scope": record.get("link_scope"),
                })

return pd.DataFrame(rows)

panels = load_panel_rows()

st.title("AI Citation Impact Dashboard")

if panels.empty: st.warning("No panel observations found.") st.stop()

panels["date"] = pd.to_datetime( panels["observed_at"], errors="coerce" ).dt.date

citation_share = ( panels.groupby("topic") .apply( lambda group: group["target_cited"].sum() / max(len(group), 1) ) .reset_index(name="citation_share") )

coverage = ( panels.groupby(["topic", "run_id"], dropna=False) .agg( panel_present=("panel_present", "max"), target_cited=("target_cited", "max"), ) .reset_index() )

coverage = ( coverage[coverage["panel_present"] == True] .groupby("topic") .apply(lambda group: group["target_cited"].mean()) .reset_index(name="citation_coverage") )

col1, col2 = st.columns(2)

with col1: st.subheader("Citation Share by Topic") st.dataframe(citation_share, use_container_width=True) st.bar_chart( citation_share.set_index("topic")["citation_share"] )

with col2: st.subheader("Citation Coverage by Topic") st.dataframe(coverage, use_container_width=True) st.bar_chart( coverage.set_index("topic")["citation_coverage"] )

st.subheader("Citation Position") st.dataframe( panels.groupby(["topic", "surface"], dropna=False) .agg( citations=("target_cited", "sum"), median_position=("position", "median"), observations=("run_id", "nunique"), ) .reset_index(), use_container_width=True, )

st.subheader("Daily Observations") daily = ( panels.groupby(["date", "surface"], dropna=False) .agg( citations=("target_cited", "sum"), observed_links=("cited_domain", "count"), ) .reset_index() )

st.line_chart( daily.pivot( index="date", columns="surface", values="citations" ).fillna(0) )

Käivitage see järgmiselt:

bash pip install streamlit pandas streamlit run dashboard.py

Tootmises laadige normaliseeritud tabelid otse DuckDB-sse, BigQuerysse, Snowflakisse või PostgreSQL-i, selle asemel et lugeda toorfailidest otse.


10. Kvaliteedikontrollid

Mõõtmissüsteem võib anda täpse välimusega, kuid eksitavaid numbreid. Lisage need kontrollid.

Eraldage robotid inimestest

Ärge kunagi loendage OAI-SearchBot'i, GPTBot'i, ClaudeBot'i ega PerplexityBot'i inimeste seanssidena. Need on roomaja- või hangitavate signaalid.

Säilitage toortõendid

Iga paneeli käivituse kohta säilitage:

  • toores HTML
  • ekraanipilt
  • vastuse tekst
  • ajatempel
  • brauseri ja kogumise versioon
  • päring ja lokaat
  • vastuse räsi

See võimaldab selgitada, miks mõõdik muutus.

Jälgige paneeli puudumist

Puuduv AI paneel ei ole sama mis vastus ilma teie viiteta.

Kasutage:

text paneel_ei_ole_kohal paneel_kohal_sihtmärk_puudub paneel_kohal_sihtmärk_viidatud blokeeritud_või_väljakutse_esitatud kogumise_viga

Kontrollige valimi kallutatust

Ajastatud kraapimist mõjutavad:

  • asukoht
  • seade
  • keel
  • aeg
  • isikupärastamine
  • brauseri olek
  • päringu sõnastus

Kasutage fikseeritud põhipäringute komplekti ja roteeruvat uurivate päringute komplekti. Hoidke need kaks rühma aruannetes eraldi.

Vältige vale täpsust

Esitage usaldusvahemikud või minimaalsed valimi suurused väikeste teemagruppide kohta. Kolme vaatlusega teemat ei tohiks otse võrrelda teemaga, mis sisaldab 300 vaatlust.

Võrrelge võrreldavaid

Platvormide võrdlemisel hoidke konstantsena:

  • päring
  • lokaat
  • riik
  • seade
  • kogumistund
  • sihtdomeeni reeglid
  • viiteparseri versioon

11. Soovitatav juurutamiskava

1. nädal: Instrumenteerimine

  • Konfigureerige struktureeritud serverilogid.
  • Looge roboti register.
  • Looge lühendaja domeen.
  • Lisage kampaania nimetamise reeglid.
  • Määratlege teema taksonoomia.
  • Lubage Google Analytics 4 BigQuery eksport.

2. nädal: Kontrollitud lingid

  • Avaldage viis kuni kümme jälgitavat kokkuvõtet.
  • Looge lingid erinevatele teemadele ja sisuversioonidele.
  • Valideerige ümbersuunamislogid analüütika seansside vastu.
  • Kinnitage, et URL-idesse ega analüütika parameetritesse ei sisestata isiklikke andmeid.

3. nädal: Paneeli vaatlused

  • Looge päringute manifest.
  • Alustage kahe platvormi ja 20 kuni 50 stabiilse päringuga.
  • Käivitage üks kord päevas.
  • Salvestage ekraanipildid ja HTML.
  • Mõõtke kogumise ebaõnnestumisi viidete puudumisest eraldi.

4. nädal: Armatuurlaud ja haldus

  • Looge teema- ja platvormipõhised armatuurlauad.
  • Lisage roomajate seisundi hoiatused.
  • Määratlege usaldusreeglid.
  • Võrrelge esimese osapoole aruandeid paneeli vaatlustega.
  • Dokumendi säilitamise, juurdepääsu ja kustutamise poliitikad.

Kokkuvõte

Tehisintellekti viidete mõõtmine tuleks ehitada mitme signaali omistamissüsteemina, mitte ühe suunamisaruandena.

Kõige usaldusväärsem raamistik kombineerib:

  • Google'i ja Bingi esimese osapoole nähtavuse aruanded
  • serverilogid roomaja ja sisu laadimise tegevuse kohta
  • esimese osapoole lühilingid kontrollitud klikimõõtmiseks
  • ajastatud, nõuetele vastavad vastuspaneeli vaatlused
  • analüütika ja konversiooniandmed allavoolu väärtuse jaoks

Kolm kõige olulisemat mõõdikut on:

  1. Viidete osakaal teema järgi — kui suur osa vaadeldud allikate ruumist kuulub teie domeenile.
  2. Abistaja suunamismäär — kui suur osa inimliiklusest on omistatav tehisintellekti platvormidele.
  3. Viitejärgne kaasamine — kas tehisintellekti kaudu suunatud külastajad teevad sisukaid tegevusi.

Süsteem muutub kasulikuks, kui iga number sisaldab oma platvormi, ajaperioodi, nimetajat, omistamise meetodit ja usaldusväärsuse taset. See distsipliin takistab roomaja tabamuste eksimist kasutajate vastu, kraabitud vastuste eksimist näitamiste vastu ja viidete eksimist äritulemuste vastu.

Seotud artiklid

Meeldib see sisu?

Telli meie uudiskiri, et saada värskeid sisuturunduse ülevaateid ja kasvujuhendeid.

See artikkel on mõeldud ainult informatiivsel eesmärgil. Sisu ja strateegiad võivad varieeruda sõltuvalt teie vajadustest.
Tehisintellekti viidete mõju mõõtmine: analüütika, logid ja paneelide kraapimine | AutoPod