How to scrape UNLIMITED Google My Business leads for FREE (April 2024)
Alex Makowski
We help B2B organizations generate 30+ qualified sales opportunities every month using cold email outreach (guaranteed, or they don't pay)
There is an easy to follow video version of this document going over exactly how to use this tool:
Before you start:
Step by Step process:
Code.js file
function doGet() {
return HtmlService.createHtmlOutputFromFile('index.html');
}
function scrapeBusinessInfoForMultipleKeywords(keywords) {
keywords.forEach(function(keyword, index) {
Utilities.sleep(1000 * index); // Delay to avoid hitting API limits
scrapeBusinessInfo(keyword.trim());
});
}
function scrapeBusinessInfo(keyword, nextPageToken = '') {
const apiKey = 'API_KEY_HERE'; // Replace with your actual API key
let apiUrl = `https://maps.googleapis.com/maps/api/place/textsearch/json?query=${encodeURIComponent(keyword)}&key=${apiKey}`;
if (nextPageToken) {
apiUrl += `&pagetoken=${nextPageToken}`;
}
const response = UrlFetchApp.fetch(apiUrl, {muteHttpExceptions: true});
const json = JSON.parse(response.getContentText());
switch (json.status) {
case 'OK':
processBusinessResults(json.results, apiKey);
if (json.next_page_token) {
Utilities.sleep(2000); // Delay for API's next page token availability
scrapeBusinessInfo(keyword, json.next_page_token);
}
break;
case 'OVER_QUERY_LIMIT':
Logger.log('Query Limit Reached');
break;
default:
Logger.log(`Error: ${json.status}`);
break;
}
}
function processBusinessResults(results, apiKey) {
results.forEach(function(business) {
const details = getBusinessDetails(business.place_id, apiKey);
const data = [
business.name,
business.formatted_address,
details.website || 'N/A',
details.formatted_phone_number || 'N/A',
];
appendDataToSheet(data);
});
}
function getBusinessDetails(placeId, apiKey) {
const detailsUrl = `https://maps.googleapis.com/maps/api/place/details/json?place_id=${placeId}&fields=formatted_phone_number,website&key=${apiKey}`;
const response = UrlFetchApp.fetch(detailsUrl, {muteHttpExceptions: true});
const json = JSON.parse(response.getContentText());
return json.result || {};
}
function appendDataToSheet(data) {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.appendRow(data);
}
Index.html
<!DOCTYPE html>
<html>
<head>
<title>Google My Business Scraper</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
background-color: #f0f0f0;
}
#container, .videos-container {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
transition: all 0.3s ease-in-out;
margin-bottom: 20px;
}
.center {
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
text-align: center;
}
textarea, button {
width: calc(100% - 22px);
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
border: 1px solid #ccc;
box-sizing: border-box;
}
textarea:focus, button:focus {
border-color: #feb650;
outline: none;
}
button {
background-color: #feb650;
color: white;
cursor: pointer;
transition: background-color 0.3s ease-in-out, transform 0.2s ease-in-out;
}
button:hover {
background-color: darken(#feb650, 5%);
transform: translateY(-2px);
}
#message {
opacity: 0;
transition: opacity 2s ease-in-out;
}
.videos-row {
display: flex;
justify-content: center;
gap: 20px; /* Adjust the space between videos */
flex-wrap: wrap;
}
.video-wrapper {
padding-top: 177.77%; /* 9:16 Aspect Ratio */
position: relative;
flex-basis: 20%; /* Adjust based on desired video size, keeping the aspect ratio */
min-width: 120px; /* Minimum width to maintain usability */
}
.video-wrapper iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
footer {
text-align: center;
margin-top: 20px;
}
a {
color: #feb650;
text-decoration: none;
transition: color 0.3s ease-in-out;
}
a:hover {
color: darken(#feb650, 10%);
}
</style>
</head>
<body>
<div id="container" class="center">
<h2>Scrape Google My Business Info</h2>
<textarea id="keywords" placeholder="Enter keywords, separated by commas"></textarea>
<button onclick="scrapeInfo()">Scrape Info</button>
<div id="message"></div>
</div>
<footer>
Built by <a target="_blank">@makowskialex_</a> from <a target="_blank">InfiniteBookings.com</a>
</footer>
<script>
function scrapeInfo() {
var keywords = document.getElementById('keywords').value.split(',');
if(keywords[0] === "") {
showMessage("Please enter at least one keyword.", "error");
return;
}
google.script.run.withSuccessHandler(function(){
showMessage("Scraping initiated. Check the sheet for updates.", "success");
}).withFailureHandler(function(err){
showMessage("Error: " + err, "error");
}).scrapeBusinessInfoForMultipleKeywords(keywords);
}
function showMessage(message, type) {
var messageDiv = document.getElementById('message');
messageDiv.innerText = message;
messageDiv.style.color = type === "error" ? "red" : "green";
messageDiv.style.opacity = 1; // Trigger fade-in
}
</script>
</body>
</html>
领英推荐
Own a B2B business?
Let us make your sales team get an extra 10-40 qualified sales calls every month on a pay-per-call basis.
Book a call to chat with us: https://infinitebookings.com/book-a-call
YouTube Vids on Cold Email:
Written format: