Build a complete personal-use Chrome extension called LeadPin that collects business listings from Google Maps, enriches them with publicly available contact information, saves local search history, and exports CSV files.
Implement the working extension, not just a mockup or implementation plan. Make reasonable decisions and complete the work without stopping for routine clarification.
PERSONAL-USE REQUIREMENTS
- All functionality must be available immediately after installation.
- No license keys, activation, license checks, subscriptions, purchase screens, checkout, pricing, plan restrictions, accounts, device tracking, or telemetry.
- No backend, hosted database, payment provider, email delivery service, paid API, or API key.
- Store settings and collected data locally.
- Network requests should only support the user’s Google Maps searches and optional business website enrichment.
- Preserve required third-party open-source license notices for any bundled assets or dependencies.
TECHNOLOGY AND STRUCTURE
- Chrome Manifest V3, minimum Chrome version 116.
- Plain JavaScript, HTML, and CSS with no extension build step.
- Use Chrome’s native side panel, opened by clicking the toolbar icon.
- Use a service worker for extension setup, a content script to interact with Maps, and IndexedDB for history.
- Suggested structure:
extension/
manifest.json
background.js
config.js
sidepanel.html
sidepanel.css
sidepanel.js
db.js
enrich.js
content/maps.js
icons/
fonts/
README.md
INSTALL.txt
package.sh - Request only necessary permissions: sidePanel, tabs, scripting, storage, and Google Maps host access. Declare HTTP/HTTPS website access as optional and request it when the email finder is enabled.
- Bundle all executable code locally and follow Manifest V3 content security rules.
SEARCH EXPERIENCE
- Search and History tabs in the side panel.
- Search form contains:
- Business type, such as “dentists”.
- Location, such as “Baner, Pune”.
- Result limit: 20, 50, 100, or All; default 20.
- Mode: Quick or Full details; default Quick.
- “Find emails and social links” switch.
- Start button.
- Open a visible Google Maps tab with English UI and search for “[business type] in [location]”.
- Reuse the same Maps tab across searches when possible.
- Allow one active run at a time.
- Collapse the form into a compact search summary after starting; provide an Edit button.
- Show live results, status text, progress, and counts for leads, phone numbers, websites, and emails.
- Show Pause/Resume and Stop controls while collecting.
- Stop work when the side panel closes and preserve already saved results.
GOOGLE MAPS COLLECTION
Quick mode:
- Read business cards from the Maps results list.
- Scroll the results feed incrementally and deduplicate listings using a stable listing identity or canonical Maps URL.
- Stop at the chosen limit, the end of the results, or a bounded no-progress condition.
- Collect only fields actually available; leave missing values blank.
Full details mode:
- Collect the result list first, then visit each business’s details pane.
- Read phone, website, full address, and opening hours in addition to available list fields.
- Support both layouts where details replace the results list and where details appear beside it.
- Restore the results list with Maps’ own Back control when necessary.
- Use conservative randomized delays, including approximately 4–8 seconds between businesses.
- Retry a failed listing once, then keep its partial row.
- Pause after five consecutive listing failures and explain how the user can continue.
- Use bounded waits and resilient selectors, favoring semantic attributes and data-item-id values.
- Check that the opened details belong to the intended listing before merging data.
- Keep selector logic centralized and easy to maintain.
- Handle empty results, a single-business result, missing controls, navigation, tab closure, and connection loss with clear messages.
- If Maps presents a CAPTCHA or access check, pause for the user to resolve it manually. Resume by redoing the search if necessary, skipping already completed listings.
- Do not implement CAPTCHA bypass, proxy rotation, or other access-control evasion.
DATA FIELDS
Preserve this CSV column order:
- Name
- Phone
- Website
- Address
- Category
- Rating
- Reviews
- Hours
- Maps link
- Sponsored
- Sponsored is Yes or No; include sponsored listings.
- Normalize whitespace.
- Store review count without formatting separators when it can be parsed reliably.
- Format hours in one cell, for example:
“Mon 10 am–9 pm; Tue 10 am–9 pm; Sun Closed”. - Never fabricate missing data.
OPTIONAL WEBSITE ENRICHMENT
- Available to everyone with no feature gating.
- Enabling the finder selects Full details mode.
- Selecting Quick mode switches the finder off.
- Request optional website access directly from the user gesture. Handle denial gracefully and check actual permission state.
- Support enrichment during a new run and through a “Find emails” button for completed or saved results.
- Fetch the business homepage and, when linked, one relevant contact page.
- Resolve relative URLs correctly.
- Extract public email addresses from text and mailto links.
- Deduplicate emails and store multiple addresses separated by semicolons.
- Filter obvious placeholders, tracking/error-reporting addresses, and asset filenames.
- Extract business Instagram, Facebook, and LinkedIn profile links; exclude sharing links.
- If the listed website is itself a supported social profile, place it in the corresponding social field without fetching that social platform.
- Use a queue with at most eight websites active concurrently.
- Apply a 10-second timeout per page and a 2 MB response-reading limit.
- Accept only HTTP/HTTPS URLs and handle redirects, network errors, non-HTML responses, and invalid URLs.
- Pause prevents new enrichment jobs from starting. Stop cancels pending work and aborts active requests where possible.
- Mark checked rows so they are not repeatedly enriched.
- Persist enrichment updates as they arrive.
- Render fetched content inertly; never execute website scripts or insert untrusted HTML into the UI.
LOCAL HISTORY
- Use IndexedDB with runs and rows stores.
- Save rows and detail updates incrementally.
- Preserve listing order and avoid duplicate rows within a run.
- Save search parameters, start time, count, mode, enrichment choice, and run status.
- Statuses: Running, Finished, Stopped, Failed, Interrupted.
- Mark unfinished runs Interrupted when reopening after closure or a crash.
- List history newest first.
- Each entry shows search, date/time, lead count, mode, and status.
- Provide Open, Export CSV, Run again, and Delete actions.
- Open loads saved results into the Search view.
- Run again restores the form; restore enrichment only if website permission remains granted.
- Provide Clear all history with a second confirmation action.
- Prevent conflicting history actions during an active run.
- Retain history until the user deletes it.
RESULTS AND CSV
- Compact table with Name, Phone, Email, and Rating first, followed by the remaining fields through horizontal scrolling.
- Keep the business name column sticky.
- Website, Maps, and social links open safely in a new tab.
- Clicking a phone number or email copies it and shows a brief toast.
- Hide result counters, table, and export controls until a run starts or saved results are opened.
- Permit export when paused, stopped, interrupted, or finished.
- Export all collected rows with the exact CSV column order above.
- Use UTF-8 with BOM, CRLF line endings, and correct escaping for commas, quotes, and newlines.
- Protect exported cells against spreadsheet formula injection.
- Filename: business-type-location-YYYY-MM-DD.csv, with sanitized slugs.
- Implement CSV only.
VISUAL DESIGN
- Polished, compact interface suitable for a narrow Chrome side panel.
- Automatically follow the system’s light/dark theme.
- Use bundled Inter if available, with system font fallbacks.
- Light palette:
background #f5f7fa
cards #ffffff
text #0d1b2a
muted text #5b6878
borders #e2e7ee
primary green #0b6e4f
yellow accent #ffb703
danger #c1121f - Dark palette:
background #0a131d
cards #101c29
text #e7edf4
borders #213246
primary green #2bb886 - Use rounded cards, subtle shadows, segmented controls, accessible focus states, and readable typography.
- Put business type and location side by side when space permits.
- Use determinate progress when the total is known and indeterminate progress for All.
- Provide clear empty, running, paused, finished, interrupted, permission-denied, and error states.
- Create a simple navy-and-yellow map-pin icon in Chrome’s required sizes.
DELIVERY AND VERIFICATION
- Produce all implementation files with no TODO placeholders, fake results, or stubbed core behavior.
- Provide unpacked-install instructions through chrome://extensions.
- Include a packaging script that creates a ZIP containing the extension folder and INSTALL.txt. Packaging must work locally without deployment.
- Explain Quick versus Full details, website permissions, local storage, CSV export, and known selector-maintenance limitations.
- Add focused tests for parsing, deduplication, CSV escaping/formula protection, and enrichment queue behavior.
- Validate manifest references and JavaScript syntax.
- Where browser access is available, verify a small live Quick run, Full details run, pause/resume, stop, history reopening, enrichment, and CSV download.
- Report precisely what was tested and identify any live checks that could not be performed.
- Finish with the generated file locations, installation steps, and verification results.