feat: Introduce Google Indexing API and IndexNow submission scripts with a unified URL gathering utility and setup guide.

This commit is contained in:
Timo Knuth
2026-01-21 13:57:58 +01:00
parent c1471830f3
commit cca1374c9e
6 changed files with 179 additions and 73 deletions

View File

@@ -1,21 +1,23 @@
// Helper script to run IndexNow submission
// Run with: npx tsx scripts/submit-indexnow.ts
// Run with: npm run submit:indexnow
import { getAllIndexableUrls, submitToIndexNow } from '../src/lib/indexnow';
async function main() {
console.log('Gathering URLs for IndexNow submission...');
console.log('🚀 Starting IndexNow Submission Script...');
console.log(' Gathering URLs for IndexNow submission...');
const urls = getAllIndexableUrls();
console.log(`Found ${urls.length} indexable URLs.`);
console.log(` Found ${urls.length} indexable URLs.`);
// Basic validation of key presence (logic can be improved)
if (!process.env.INDEXNOW_KEY) {
console.warn('⚠️ WARNING: INDEXNOW_KEY environment variable is not set. Using placeholder.');
// In production, you'd fail here. For dev/demo, we proceed but expect failure from API.
console.warn('⚠️ WARNING: INDEXNOW_KEY environment variable is not set.');
console.warn(' The submission might fail if the key is not hardcoded in src/lib/indexnow.ts');
}
await submitToIndexNow(urls);
console.log('\n✨ IndexNow submission process completed.');
}
main().catch(console.error);

View File

@@ -1,66 +0,0 @@
const { google } = require('googleapis');
const fs = require('fs');
const path = require('path');
// KONFIGURATION
// ==========================================
// Pfad zu deinem Service Account Key
const KEY_FILE = path.join(__dirname, '../service_account.json');
// Liste der URLs, die du indexieren willst
const URLS_TO_INDEX = [
'https://www.qrmaster.net/tools/barcode-generator',
// Füge hier weitere URLs hinzu
];
// ==========================================
async function runUsingServiceAccount() {
if (!fs.existsSync(KEY_FILE)) {
console.error('❌ FEHLER: service_account.json nicht gefunden!');
console.error(' Bitte befolge die Anleitung in INDEXING_GUIDE.md und speichere den Key im Hauptordner.');
return;
}
console.log(`🔑 Authentifiziere mit Key-File: ${KEY_FILE}...`);
const auth = new google.auth.GoogleAuth({
keyFile: KEY_FILE,
scopes: ['https://www.googleapis.com/auth/indexing'],
});
const client = await auth.getClient();
// console.log(`🔑 Authentifiziere als: ${key.client_email}...`);
try {
// await jwtClient.authorize(); // Nicht mehr nötig mit GoogleAuth
console.log('✅ Authentifizierung erfolgreich.');
for (const url of URLS_TO_INDEX) {
console.log(`🚀 Sende Indexierungs-Anfrage für: ${url}`);
const result = await google.indexing('v3').urlNotifications.publish({
auth: client,
requestBody: {
url: url,
type: 'URL_UPDATED'
}
});
console.log(` Status: ${result.status} ${result.statusText}`);
console.log(` Server Antwort:`, result.data);
}
console.log('\n✨ Fertig! Google wurde benachrichtigt.');
console.log(' Hinweis: Es kann immer noch ein paar Stunden dauern, bis Änderungen sichtbar sind.');
} catch (error) {
console.error('\n❌ Es ist ein Fehler aufgetreten:');
console.error(error.message);
if (error.response) {
console.error('Details:', error.response.data);
}
}
}
runUsingServiceAccount();

View File

@@ -0,0 +1,81 @@
import { google } from 'googleapis';
import fs from 'fs';
import path from 'path';
import { getAllIndexableUrls } from '../src/lib/indexnow';
// ==========================================
// CONFIGURATION
// ==========================================
// Path to your Service Account Key (JSON file)
const KEY_FILE = path.join(__dirname, '../service_account.json');
// Urls are now fetched dynamically from src/lib/indexnow.ts
// ==========================================
async function runUsingServiceAccount() {
console.log('🚀 Starting Google Indexing Script (All Pages)...');
if (!fs.existsSync(KEY_FILE)) {
console.error('\n❌ ERROR: Service Account Key not found!');
console.error(` Expected path: ${KEY_FILE}`);
console.error(' Please follow the instructions in INDEXING_GUIDE.md to create and save the key.');
return;
}
console.log(`🔑 Authenticating with key file: ${path.basename(KEY_FILE)}...`);
const auth = new google.auth.GoogleAuth({
keyFile: KEY_FILE,
scopes: ['https://www.googleapis.com/auth/indexing'],
});
try {
const client = await auth.getClient();
console.log('✅ Authentication successful.');
console.log(' Gathering URLs to index...');
const allUrls = getAllIndexableUrls();
console.log(` Found ${allUrls.length} URLs to index.`);
for (const url of allUrls) {
console.log(`\n📄 Processing: ${url}`);
try {
const result = await google.indexing('v3').urlNotifications.publish({
auth: client,
requestBody: {
url: url,
type: 'URL_UPDATED'
}
});
console.log(` 👉 Status: ${result.status} ${result.statusText}`);
// Optional: Log more details from result.data if needed
} catch (innerError: any) {
console.error(` ❌ Failed to index ${url}`);
if (innerError.response) {
console.error(` Reason: ${innerError.response.status} - ${JSON.stringify(innerError.response.data)}`);
// 429 = Quota exceeded
// 403 = Permission denied (check service account owner status)
} else {
console.error(` Reason: ${innerError.message}`);
}
}
// Optional: Add a small delay to avoid hitting rate limits too fast if you have hundreds of URLs
// await new Promise(resolve => setTimeout(resolve, 500));
}
console.log('\n✨ Done! All requests processed.');
console.log(' Note: Check Google Search Console for actual indexing status over time.');
} catch (error: any) {
console.error('\n❌ Fatal error occurred:');
console.error(error.message);
}
}
runUsingServiceAccount();