SEO indexing bot

kliz

Une API Python agnostique pour notifier IndexNow et Google Indexing quand une URL est créée, mise à jour ou prête à être redécouverte.

Installation

Kliz reste volontairement léger côté intégration : pas de Django, pas de Celery, pas de Redis imposé par le package.

Terminal
pip install kliz

Synchrone

Tu appelles l'API depuis ton service, worker ou cron existant.

Agnostique

Le package ne force aucun framework web ni file d'attente.

Typed

Le package expose `py.typed` et passe en typage strict.

Démarrage rapide

Injecte les providers dans l'orchestrateur, puis notifie une URL. Les erreurs d'un provider n'arrêtent pas les autres providers.

Python
from kliz import GoogleProvider, IndexNowProvider, Kliz

indexer = Kliz(
    [
        IndexNowProvider(
            api_key="votre-cle-indexnow",
            key_location="https://example.com/votre-cle-indexnow.txt",
        ),
        GoogleProvider("/run/secrets/google-service-account.json"),
    ]
)

statuses = indexer.notify_all("https://example.com/articles/nouvel-article")
Lots + retry opt-in
indexer = Kliz(
    [IndexNowProvider(api_key="votre-cle-indexnow")],
    max_attempts=3,
)

statuses = indexer.notify_many([
    "https://example.com/articles/a",
    "https://example.com/articles/b",
])
Résultats détaillés
results = indexer.notify_all_detailed(
    "https://example.com/articles/nouvel-article"
)

for name, result in results.items():
    print(name, result.success, result.retryable, result.error)

Providers

Chaque provider respecte le même contrat : `notify(url) -> bool`. L'orchestrateur reste stable quand un moteur est ajouté.

IndexNow

Envoie une ou plusieurs URL du même hôte. Les réponses `429` et `5xx` sont classées comme retentables.

Python
provider = IndexNowProvider(
    api_key="votre-cle-valide",
    key_location="https://example.com/votre-cle-valide.txt",
)

provider.notify_many([
    "https://example.com/page-1",
    "https://example.com/page-2",
])

Google Indexing

Publie une notification `URL_UPDATED` pour les pages officiellement éligibles selon Google.

Python
provider = GoogleProvider(
    "/run/secrets/google-service-account.json",
    timeout=60.0,
    num_retries=2,
)

provider.notify("https://example.com/jobs/backend-python")
Google Indexing est réservé aux pages contenant un `JobPosting` ou un `BroadcastEvent` intégré dans un `VideoObject`. Pour les autres contenus, garde un sitemap propre.
`BatchProvider` (exporté publiquement) est la base commune de tous les moteurs par lots : elle gère le découpage selon `max_urls_per_request` et le repli en boucle `notify`. Pour ajouter un moteur, implémentez `_notify_many(urls)` ; les helpers HTTP partagés (`_http.py`) sont fournis.

CLI

Après installation, la commande kliz permet de notifier une URL ou un lot, et de lister les providers configurés. Les credentials passent par des variables d'environnement KLIZ_* ou des options CLI.

Terminal
export KLIZ_INDEXNOW_API_KEY="votre-cle"
export KLIZ_INDEXNOW_KEY_LOCATION="https://example.com/votre-cle.txt"

kliz notify https://example.com/page
kliz notify --batch urls.txt
kliz providers
kliz --version
Code de sortie : 0 succès, 1 échec de notification, 2 configuration invalide.

Intégration asynchrone

Kliz ne transporte pas de système de jobs. Place simplement l'appel dans le worker déjà utilisé par ton application.

Celery
from dataclasses import asdict

from celery import shared_task
from django.conf import settings
from kliz import IndexNowProvider, Kliz


@shared_task(bind=True, max_retries=5)
def notify_search_engines(self, url: str):
    indexer = Kliz([
        IndexNowProvider(
            api_key=settings.INDEXNOW_API_KEY,
            key_location=settings.INDEXNOW_KEY_LOCATION,
        )
    ])
    results = indexer.notify_all_detailed(url)
    retryable = [result for result in results.values() if result.retryable]

    if retryable:
        raise self.retry(countdown=60)

    return {name: asdict(result) for name, result in results.items()}

Production

Une notification accélère la découverte, mais ne garantit jamais l'indexation. Le monitoring et les retries restent côté application.

  1. Injecter les secrets depuis un gestionnaire prévu pour ça.
  2. Appliquer un backoff avec jitter aux erreurs retentables.
  3. Suivre les statuts HTTP, quotas, latences et taux de succès.
  4. Garder un sitemap à jour pour la couverture générale.

Validation locale

`pytest`, `ruff`, `mypy`, `build`, `twine` et `pip-audit`.

Licence

MIT, avec contribution et politique de sécurité documentées.