A .NET 10 Worker Service that automatically submits URLs to Google's Indexing API from your sitemap, helping to keep Google's index fresh and up-to-date with your website content.
- 🔄 Automatic URL Indexing - Submits URLs from your sitemap to Google's Indexing API
- 📊 Daily Quota Management - Respects daily API limits (default: 200 URLs/day)
- 💾 State Persistence - Tracks progress and resumes from where it left off on restart
- 🔁 Circular Indexing - Automatically cycles through all URLs, starting from beginning when complete
- 📅 Daily Reset - Quota resets automatically each day
- 📝 Comprehensive Logging - Serilog integration with file and console output
- 📧 Email Notifications - Optional error notifications via email
- 🪟 Windows Service - Runs as a Windows Service for automated execution
- ⚡ One-Shot Execution - Indexes up to quota limit per run, designed for scheduled execution
- .NET 10 Runtime
- Google Service Account credentials (JSON file or inline)
- Valid sitemap URL
- Windows Server (for Windows Service deployment)
Create Google Service Account:
- Go to Google Cloud Console
- Create a new project or select existing
- Enable the "Indexing API"
- Create a Service Account and download the JSON key file
- Share your property with the service account in Google Search Console
Edit appsettings.json:
{
"AppSettings": {
"GoogleCredentials": "path-to-your-credentials.json",
"SitemapUrl": "https://yourdomain.com/sitemap.xml",
"StateFile": "indexing-state.json",
"DailyQuota": 200,
"RunIntervalMinutes": 5,
"LogsExpirationDays": 14,
"PrioritizeSitemap": true
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"SerilogEmail": {
"From": "",
"To": "",
"MailServer": "",
"Port": 587,
"EnableSsl": true,
"Username": "",
"Password": "",
"Subject": "Google Indexing Service - Errors",
"BatchPostingLimit": 100,
"BatchPostingPeriodMinutes": 60
},
"SerilogSeq": {
"ServerUrl": "",
"ApiKey": ""
}
}Configuration Options:
| Setting | Description | Example |
|---|---|---|
GoogleCredentials |
Path to Google Service Account JSON file | google-key.json |
SitemapUrl |
URL to your sitemap.xml | https://yoursite.com/sitemap.xml |
StateFile |
Path to state tracking file (relative to AppContext.BaseDirectory) | indexing-state.json |
DailyQuota |
Maximum URLs to index per day (Google's limit: 200/day) | 200 |
RunIntervalMinutes |
Unused (service runs once per execution) | 5 |
LogsExpirationDays |
Days to retain log files | 14 |
PrioritizeSitemap |
Sort URLs by sitemap priority if available | true |
Email Notifications (Optional):
"SerilogEmail": {
"From": "noreply@yourdomain.com",
"To": "admin@yourdomain.com",
"MailServer": "smtp.yourdomain.com",
"Port": 587,
"EnableSsl": true,
"Username": "your-email@yourdomain.com",
"Password": "your-password",
"Subject": "Google Indexing Service - Errors",
"BatchPostingLimit": 100,
"BatchPostingPeriodMinutes": 60
}Seq Integration (Optional):
"SerilogSeq": {
"ServerUrl": "https://seq.yourdomain.com",
"ApiKey": "your-seq-api-key"
}Place your Google Service Account JSON file in the application directory:
C:\Services\GoogleIndexingService\
├── GoogleIndexingService.exe
├── appsettings.json
├── google-key.json ← Your credentials here
└── indexing-state.json ← Auto-created on first run
# Build the project
dotnet publish -c Release -o "C:\Services\GoogleIndexingService"
# Copy your credentials file
Copy-Item "google-key.json" -Destination "C:\Services\GoogleIndexingService\"
# Install as Windows Service
sc.exe create GoogleIndexingService binPath= "C:\Services\GoogleIndexingService\GoogleIndexingService.exe"
# Set to run as NETWORK SERVICE (or appropriate account)
sc.exe config GoogleIndexingService obj= "NT AUTHORITY\NETWORK SERVICE"
# Grant file access permissions (optional)
icacls "C:\Services\GoogleIndexingService" /grant "NT AUTHORITY\NETWORK SERVICE:(OI)(CI)F" /T
# Start the service
net start GoogleIndexingServicedotnet GoogleIndexingService.dll# Start
net start GoogleIndexingService
# Stop
net stop GoogleIndexingService
# Check status
sc.exe query GoogleIndexingService
# View recent logs
Get-Content "Logs\indexing-*.log" -Tail 50Daily at 2 AM using Task Scheduler:
- Open Task Scheduler
- Create Basic Task
- Set trigger: Daily at 2:00 AM
- Set action:
- Program:
C:\Services\GoogleIndexingService\GoogleIndexingService.exe - Start in:
C:\Services\GoogleIndexingService
- Program:
- Load Configuration - Reads appsettings.json
- Load Credentials - Reads Google Service Account JSON file
- Fetch Sitemap - Downloads and parses your sitemap.xml
- Check Quota - Verifies daily quota hasn't been reached
- Resume Position - Starts from NextIndex (where previous run ended)
- Index URLs - Submits each URL to Google's Indexing API
- Track Progress - Updates position and daily count
- Save State - Persists progress to indexing-state.json
- Wrap Around - After indexing all URLs, starts from beginning on next day
State is tracked in indexing-state.json:
{
"LastRunDate": "2024-01-15T00:00:00Z",
"DailyCount": 45,
"NextIndex": 50
}- LastRunDate - Last execution date (resets daily count if new day)
- DailyCount - URLs indexed today
- NextIndex - Position to resume from on next run
Logs are written to:
- Console - Real-time output for debugging
- Files -
Logs/indexing-YYYY-MM-DD.log(rolling daily, keeps 14 days) - Email - Optional error notifications (if configured)
- Seq - Optional centralized logging (if configured)
Successful indexing:
[10:28:29 INF] Indexing service starting. Max quota: 200 URLs.
[10:28:29 INF] Found 1000 URLs to index.
[10:28:29 INF] Resuming from URL index 200 (yesterday indexed 200 URLs).
[10:28:29 INF] Indexed https://yourdomain.com/page-1.
[10:28:30 INF] Indexed https://yourdomain.com/page-2.
[10:28:31 INF] Indexing completed: 200 succeeded, 0 failed. Total today: 200/200.
[10:28:31 INF] State saved. Next run will start from URL index 400.
Quota exceeded:
[10:28:35 WRN] Quota exceeded while indexing https://yourdomain.com/page-5.
[10:28:35 INF] Quota exceeded after indexing 4 more URLs (total today: 204).
- Check Event Viewer - Look for error details in Windows Event Viewer
- Verify credentials file - Ensure
google-key.jsonexists and is valid JSON - Check permissions - Service account needs read access to all files
- Test standalone - Run
dotnet GoogleIndexingService.dlldirectly to see errors
- Verify sitemap URL - Test accessing it in browser
- Check credentials file - Ensure it's valid and authorized for Indexing API
- Check Google API - Verify Indexing API is enabled in Cloud Console
- Property access - Ensure service account has access to property in Search Console
- Review logs - Check
Logs/indexing-*.logfor error messages
- Delete
indexing-state.jsonand restart service - Service will create new state and start from beginning
- Check
LastRunDatein state file - Ensure system time is correct
- If stuck, delete state file and restart
- Ensure
google-key.jsonis in the same directory asGoogleIndexingService.exe - Check
AppSettings:GoogleCredentialsin appsettings.json matches the actual filename - Verify file permissions allow the service account to read it
Services/
├── Interfaces/
│ ├── IIndexingServiceClient.cs - Google Indexing API client
│ ├── IUrlProvider.cs - Sitemap URL fetching
│ └── IIndexingStateStore.cs - State persistence
├── IndexingServiceClient.cs - Google API implementation
├── UrlProvider.cs - Sitemap parsing
└── IndexingStateStore.cs - State file I/O
Models/
├── IndexingResult.cs - Result enum (Success/Failure/QuotaExceeded)
└── IndexingState.cs - State model
Settings/
└── AppSettings.cs - Configuration model
Logging/
└── SerilogConfigurationExtensions.cs - Serilog setup
Worker.cs - Main service logic (BackgroundService)
Program.cs - DI and configuration setup
dotnet builddotnet run- Network calls: 1 per run (sitemap fetch) + 1 per URL (Google API)
- Memory: ~10-50 MB depending on sitemap size
- Disk I/O: Minimal (state file write only)
- CPU: Light processing (XML parsing, JSON serialization)
For 10,000 URL sitemaps with 200 quota: ~2-5 minutes per run
This project is licensed under the MIT License.
For issues, check:
- Log files in
Logs/directory - Google Cloud Console for API errors
- Windows Event Viewer for service errors
- Ensure credentials file is accessible
- Verify sitemap URL is publicly accessible
© 2026-present calKU0