Publishing new pages, site revamps, or frequent blog updates often leads to one tedious bottleneck: manually inspecting URLs and requesting indexing inside Google Search Console (GSC). Waiting 30 to 45 seconds per page to click “Request Indexing” quickly consumes valuable hours.
By combining Microsoft Excel VBA, SeleniumBasic, and Chrome Remote Debugging, you can automate the entire submission pipeline directly from a spreadsheet without dealing with the limitations of the official Google Indexing API.
Why Use Chrome Remote Debugging with VBA?
Standard browser automation frameworks often trigger bot detection or run into Google's strict OAuth and 2FA login walls. By connecting to Chrome via a dedicated debugging port (127.0.0.1:9222), your VBA script attaches to an already authenticated browser profile.
This approach offers significant advantages:
No Authentication Friction: Stay logged into your Google account without saving credentials in code.
Smart Filtering: Automatically skip links marked as "Submitted" or "Already Indexed" to conserve your daily quota.
Direct UI Interaction: Native JavaScript execution bypasses stubborn Material UI modals and ensures reliable element clicks.
Step 1: Install SeleniumBasic & Setup ChromeDriver
Before writing macros, your environment requires two core components to bridge Excel and Chrome:
Install SeleniumBasic:
Download
SeleniumBasic-2.0.9.0.exefrom GitHub releases.Run the installer. By default, it installs to:
PlaintextC:\Users\%USERNAME%\AppData\Local\SeleniumBasic(or
C:\Program Files\SeleniumBasicdepending on installation scope).
Match & Replace ChromeDriver:
Open Chrome and navigate to
chrome://settings/helpto check your browser version.Download the matching ChromeDriver binary for your operating system.
Extract
chromedriver.exeand copy it into your SeleniumBasic installation folder, replacing the existing, older driver file.
Step 2: Launch Chrome in Remote Debugging Mode
Ensure all background instances of Google Chrome are closed before starting. You can verify this via Windows Task Manager.
Open Command Prompt or a Run dialog (
Win + R).Run the command below to launch Chrome with an open debugging port:
chrome.exe --remote-debugging-port=9222 --user-data-dir="C:\selenium\ChromeProfile"
In this browser window, navigate to Google Search Console and select your verified property.
Step 3: Configure the Excel Workbook
Open a new Excel workbook.
Structure Sheet1 as follows:
Column A: Target URLs to inspect and submit.
Column B: Status output (e.g.,
Submitted,Already Indexed,Daily Quota Exceeded).
Press
Alt + F11to enter the Visual Basic Editor.Navigate to Tools > References, locate Selenium Type Library, check the box, and click OK.
Click Insert > Module and paste the automation script.
Step 4: The Automation Script
Sub RequestIndexingGSC()
On Error Resume Next
Application.VBE.MainWindow.Visible = False
On Error GoTo 0
Dim driver As Selenium.ChromeDriver
Dim ws As Worksheet
Dim lastRow As Long, i As Long
Dim targetUrl As String, currentStatus As String, verdictStatus As String
Dim inspectInput As Selenium.WebElement
Dim clickSuccess As Boolean, dismissSuccess As Boolean
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
If lastRow < 2 Then
MsgBox "No URLs found in Column A.", vbExclamation
Exit Sub
End If
' Attach to the active Chrome debugging session
Set driver = New Selenium.ChromeDriver
driver.SetCapability "debuggerAddress", "127.0.0.1:9222"
driver.Start "chrome"
For i = 2 To lastRow
targetUrl = Trim(ws.Cells(i, 1).Value)
currentStatus = Trim(ws.Cells(i, 2).Value)
ws.Cells(i, 2).Activate
' Skip previously completed rows
If LCase(currentStatus) = "submitted" Then GoTo NextUrl
If Len(targetUrl) > 0 Then
Call WaitForIndexFetch(driver, 15)
' Locate the inspection search bar
Set inspectInput = PollForElement(driver, "//input[@role='combobox' or @type='text']", 15)
If inspectInput Is Nothing Then
ws.Cells(i, 2).Value = "Search Bar Not Located"
GoTo NextUrl
End If
' Submit URL
driver.ExecuteScript "arguments[0].focus(); arguments[0].select();", inspectInput
inspectInput.Clear
inspectInput.SendKeys targetUrl
inspectInput.SendKeys driver.Keys.Enter
' Wait for index retrieval
Call WaitForIndexFetch(driver, 40)
' Evaluate URL status
verdictStatus = PollForVerdict(driver, 20)
If verdictStatus = "Indexed" Then
ws.Cells(i, 2).Value = "Already Indexed"
GoTo NextUrl
ElseIf verdictStatus = "Timeout" Then
ws.Cells(i, 2).Value = "Inspection Timeout"
GoTo NextUrl
End If
' Trigger Indexing Request
clickSuccess = ClickRequestIndexingDirect(driver, 25)
If Not clickSuccess Then
If driver.FindElementsByXPath("//*[contains(translate(text(), 'QUOTA', 'quota'), 'quota')]").Count > 0 Then
ws.Cells(i, 2).Value = "Daily Quota Exceeded"
Else
ws.Cells(i, 2).Value = "Request Button Missing"
End If
GoTo NextUrl
End If
' Dismiss the confirmation modal
dismissSuccess = ClickDismissModalDirect(driver, 60)
If dismissSuccess Then
Call WaitForDialogClose(driver, 5)
ws.Cells(i, 2).Value = "Submitted"
Else
If driver.FindElementsByXPath("//*[contains(translate(text(), 'QUOTA', 'quota'), 'quota')]").Count > 0 Then
ws.Cells(i, 2).Value = "Daily Quota Exceeded"
Else
ws.Cells(i, 2).Value = "Live Test Timeout (60s)"
End If
End If
End If
NextUrl:
Next i
On Error Resume Next
Application.VBE.MainWindow.Visible = True
On Error GoTo 0
MsgBox "Indexing batch completed!", vbInformation
End Sub
' --- Helper Functions ---
Function ClickRequestIndexingDirect(driver As Selenium.ChromeDriver, maxSeconds As Single) As Boolean
Dim attempts As Long, maxAttempts As Long, res As Boolean
maxAttempts = CLng(maxSeconds * 5)
For attempts = 1 To maxAttempts
On Error Resume Next
res = CBool(driver.ExecuteScript( _
"var nodes = Array.from(document.querySelectorAll('span, div, button'));" & _
"for (var i = 0; i < nodes.length; i++) {" & _
" var txt = (nodes[i].innerText || nodes[i].textContent || '').trim().toLowerCase();" & _
" if (txt === 'request indexing' || txt === 'request again') {" & _
" var btn = nodes[i].closest('div[role=""button""], button') || nodes[i];" & _
" btn.scrollIntoView({block: 'center'});" & _
" btn.click(); return true;" & _
" }" & _
"} return false;"))
If res Then ClickRequestIndexingDirect = True: Exit Function
On Error GoTo 0
driver.Wait 200
Next attempts
ClickRequestIndexingDirect = False
End Function
Function ClickDismissModalDirect(driver As Selenium.ChromeDriver, maxSeconds As Single) As Boolean
Dim attempts As Long, maxAttempts As Long, res As Boolean
maxAttempts = CLng(maxSeconds * 5)
For attempts = 1 To maxAttempts
On Error Resume Next
res = CBool(driver.ExecuteScript( _
"var btns = Array.from(document.querySelectorAll('div[role=""dialog""] button, div[role=""dialog""] div[role=""button""]'));" & _
"for (var i = 0; i < btns.length; i++) {" & _
" var txt = (btns[i].innerText || btns[i].textContent || '').trim().toLowerCase();" & _
" var action = btns[i].getAttribute('data-mdc-dialog-action') || '';" & _
" if (txt === 'got it' || txt === 'dismiss' || txt === 'ok' || action.toLowerCase() === 'ok') {" & _
" btns[i].scrollIntoView({block: 'center'});" & _
" btns[i].click(); return true;" & _
" }" & _
"} return false;"))
If res Then ClickDismissModalDirect = True: Exit Function
On Error GoTo 0
driver.Wait 200
Next attempts
ClickDismissModalDirect = False
End Function
Function PollForElement(driver As Selenium.ChromeDriver, xpath As String, maxSeconds As Single) As Selenium.WebElement
Dim attempts As Long, maxAttempts As Long
maxAttempts = CLng(maxSeconds * 5)
For attempts = 1 To maxAttempts
On Error Resume Next
Dim elements As Selenium.WebElements
Set elements = driver.FindElementsByXPath(xpath)
If Not elements Is Nothing Then
If elements.Count > 0 Then
If elements.Item(1).IsDisplayed Then
Set PollForElement = elements.Item(1)
Exit Function
End If
End If
End If
On Error GoTo 0
driver.Wait 200
Next attempts
Set PollForElement = Nothing
End Function
Sub WaitForIndexFetch(driver As Selenium.ChromeDriver, maxSeconds As Single)
Dim attempts As Long, maxAttempts As Long
maxAttempts = CLng(maxSeconds * 5)
driver.Wait 400
For attempts = 1 To maxAttempts
On Error Resume Next
If driver.FindElementsByXPath("//*[contains(text(), 'Retrieving data from Google Index')]").Count = 0 Then Exit Sub
On Error GoTo 0
driver.Wait 200
Next attempts
End Sub
Function PollForVerdict(driver As Selenium.ChromeDriver, maxSeconds As Single) As String
Dim attempts As Long, maxAttempts As Long
maxAttempts = CLng(maxSeconds * 5)
For attempts = 1 To maxAttempts
On Error Resume Next
If driver.FindElementsByXPath("//*[contains(text(),'URL is not on Google')]").Count > 0 Then
PollForVerdict = "NotIndexed": Exit Function
End If
If driver.FindElementsByXPath("//div[normalize-space(text())='URL is on Google']").Count > 0 Then
PollForVerdict = "Indexed": Exit Function
End If
On Error GoTo 0
driver.Wait 200
Next attempts
PollForVerdict = "Timeout"
End Function
Function WaitForDialogClose(driver As Selenium.ChromeDriver, maxSeconds As Single) As Boolean
Dim attempts As Long, maxAttempts As Long
maxAttempts = CLng(maxSeconds * 5)
For attempts = 1 To maxAttempts
On Error Resume Next
If driver.FindElementsByXPath("//div[@role='dialog']").Count = 0 Then
WaitForDialogClose = True: Exit Function
End If
On Error GoTo 0
driver.Wait 200
Next attempts
WaitForDialogClose = False
End Function
Best Practices & Quota Considerations
Daily Limits: Google enforces an account/property quota on manual inspection and index requests (typically between 10 to 50 requests per 24-hour cycle). The script flags
"Daily Quota Exceeded"when this threshold is reached.Wait Times: Do not artificially shorten the polling delays. Google's live URL test requires 15 to 40 seconds to process response headers, mobile rendering, and canonical tags.
Background Chrome Instances: If the script throws a connection error on port 9222, ensure no hidden Chrome processes are running before launching your custom debugging session.
Leave a Comment
Your email address will not be published.
0 Comments
No comments yet. Be the first to comment.