Анализ и оптимизация индексации страниц сайта (Index Coverage)
Index Coverage — соотношение между страницами, которые есть на сайте, и страницами, которые Google действительно проиндексировал. Многие проблемы с SEO-трафиком объясняются не качеством контента, а тем, что страницы просто не попали в индекс.
Google Search Console: Coverage отчёт
GSC → Index → Pages делит все обнаруженные URL на категории:
Indexed — страницы в индексе (цель: 80–95% от общего числа URL).
Crawled - currently not indexed — Google видел, но не стал индексировать. Причины: thin content, низкое качество, слишком много похожего контента.
Discovered - currently not indexed — Google нашёл URL, но ещё не краулил. Обычно из-за перегрузки crawl budget.
Not indexed — noindex — явная директива не индексировать.
Duplicate — дублирующиеся страницы (Google выбрал canonical).
Excluded by robots.txt — заблокированные в robots.txt.
Выгрузка всех URL и их статусов
# Google Search Console API
from googleapiclient.discovery import build
from oauth2client.service_account import ServiceAccountCredentials
credentials = ServiceAccountCredentials.from_json_keyfile_name(
'gsc-credentials.json',
['https://www.googleapis.com/auth/webmasters.readonly']
)
service = build('searchconsole', 'v1', credentials=credentials)
# URL Inspection API — проверить конкретный URL
response = service.urlInspection().index().inspect(
body={
'inspectionUrl': 'https://company.com/products/iphone-15',
'siteUrl': 'https://company.com/'
}
).execute()
indexing_state = response['inspectionResult']['indexStatusResult']['indexingState']
# INDEXING_ALLOWED, NOT_INDEXED, etc.
Диагностика "Crawled - currently not indexed"
Наиболее сложная категория для исправления — Google видит страницу, но не считает её достойной индексации.
def diagnose_not_indexed_pages(urls):
issues = []
for url in urls:
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# Подсчёт слов
text = ' '.join(soup.get_text().split())
word_count = len(text.split())
# Проверка уникальности title среди страниц сайта
title = soup.find('title').text if soup.find('title') else ''
issues.append({
'url': url,
'word_count': word_count,
'title': title,
'has_canonical': bool(soup.find('link', rel='canonical')),
'robots': soup.find('meta', attrs={'name': 'robots'}),
'h1_count': len(soup.find_all('h1')),
})
# Thin content
thin = [p for p in issues if p['word_count'] < 300]
print(f"Thin content ({len(thin)} pages):")
for p in thin[:10]:
print(f" {p['url']}: {p['word_count']} words")
Исправление распространённых проблем
Thin content — меньше 300 слов. Решение: расширить контент или объединить похожие страницы:
<!-- Объединить: /tag/iphone + /tag/apple + /tag/smartphones → одна страница -->
<!-- Или добавить уникальный контент на каждую тег-страницу -->
Дублирующийся контент без canonical:
<!-- На ВСЕХ вариантах URL одной страницы -->
<link rel="canonical" href="https://site.com/products/iphone-15">
<!-- Включая: ?utm_source=*, ?sort=*, /iphone-15/, http://... -->
Noindex по ошибке:
# Найти noindex на важных страницах
grep -r "noindex" /var/www/templates/ | grep -v ".git"
# Через краулинг
python -c "
import requests
from bs4 import BeautifulSoup
for url in important_urls:
r = requests.get(url)
soup = BeautifulSoup(r.text, 'html.parser')
robots = soup.find('meta', attrs={'name': 'robots'})
if robots and 'noindex' in robots.get('content', '').lower():
print(f'NOINDEX: {url}')
"
Страницы только за авторизацией:
<!-- Публичный контент должен быть доступен без cookies -->
<!-- Проверить через: curl -c /dev/null https://site.com/page -->
Sitemap как инструмент ускорения индексации
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://company.com/products/iphone-15</loc>
<lastmod>2024-03-15</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
</url>
</urlset>
Ping Google об обновлении sitemap:
curl "https://www.google.com/ping?sitemap=https://company.com/sitemap.xml"
IndexNow API (Bing, Yandex):
curl -X POST https://api.indexnow.org/IndexNow \
-H "Content-Type: application/json" \
-d '{
"host": "company.com",
"key": "your-key",
"urlList": ["https://company.com/new-page", "https://company.com/updated-page"]
}'
Мониторинг динамики индексации
def track_indexation_rate(history_db):
"""Отслеживать % проиндексированных страниц в динамике"""
total_published = count_published_pages()
indexed_count = get_gsc_indexed_count()
rate = indexed_count / total_published * 100
history_db.save({'date': datetime.now(), 'rate': rate, 'indexed': indexed_count})
# Алерт при снижении
last_week = history_db.get_7days_ago()
if rate < last_week.rate - 5: # снижение более 5%
send_alert(f"Index coverage dropped from {last_week.rate:.1f}% to {rate:.1f}%")
Срок выполнения
Аудит Index Coverage + план устранения проблем — 2–3 рабочих дня.







