Google Maps Competitor Change Tracker
Pricing
$10.00 / 1,000 qualified competitor change results
Google Maps Competitor Change Tracker
Compare structured Google Maps listing snapshots or persist a monitor baseline to detect explainable competitor changes, review velocity, closures, category moves, profile updates, and new or removed listings.
Pricing
$10.00 / 1,000 qualified competitor change results
Rating
0.0
(0)
Developer
Khoa Nguyen
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
16 days ago
Last modified
Categories
Share
Turn two structured Google Maps listing snapshots into explainable competitor alerts, or run in monitor mode and compare each new snapshot with a baseline stored in Apify Key-Value Store.
This Actor is designed for local SEO agencies, franchise operators, multi-location brands, and competitive-intelligence teams. It does not scrape Google Maps directly. It accepts listing data from an existing compliant data source, normalizes common scraper/export formats, safely matches entities, detects meaningful changes, scores impact, and publishes an agency-ready report.
What it detects
- New and removed competitors
- Business status changes, including temporary and permanent closure
- Rating, review-count, and review-velocity movement
- Primary and secondary category changes
- Opening-hours changes
- Name, address, phone, website, and coordinate changes
- Price-level and claimed-profile changes
- Photo-count, description, attributes, and service-option changes
- Booking, ordering, and menu URL changes
Each alert contains the before/after evidence, matching method, confidence, field-level explanations, impact score, severity, and a recommended action.
Two-minute start
The default input runs fully offline and requires no credentials:
{"runMode": "demo"}
The demo uses realistic bundled fixtures but sends them through the same normalization, validation, deduplication, matching, diff, scoring, filtering, dataset, and report pipeline used by live inputs.
Expected default output:
- Non-empty default dataset with qualified alert records
OUTPUTsummary in the default Key-Value StoreREPORT.mdhuman-readable reportNORMALIZED_CURRENTnormalized snapshotMATCH_DIAGNOSTICSdata-quality and matching evidence
Input modes
Compare two snapshots
Provide two inline arrays:
{"runMode": "compare","previousObservedAt": "2026-06-01T00:00:00Z","currentObservedAt": "2026-07-01T00:00:00Z","previousSnapshot": [{"placeId": "ChIJ-example-1","name": "Alpha Dental","address": "1 Main Street","rating": 4.4,"reviewCount": 120}],"currentSnapshot": [{"placeId": "ChIJ-example-1","name": "Alpha Dental","address": "1 Main Street","rating": 4.6,"reviewCount": 146,"bookingUrl": "https://alpha-dental.example/book"}]}
You can instead provide public HTTPS URLs with previousSnapshotUrl and currentSnapshotUrl. URL sources can return JSON arrays, objects containing items, results, or data, JSONL/NDJSON, or CSV.
Monitor a recurring baseline
First run:
{"runMode": "monitor","baselineKey": "COMPETITOR_DETROIT_DENTISTS","currentSnapshot": [{"placeId": "ChIJ-example-1","name": "Alpha Dental","rating": 4.6,"reviewCount": 146}]}
The default firstRunBehavior is store-and-exit, so the first run creates the baseline without generating false “new competitor” alerts. Later runs load that state, compare it with the new snapshot, and update the baseline only after processing and persistence complete successfully. When the SDK reports that the pay-per-event limit was reached, the baseline is not advanced, preventing silent loss of undelivered changes.
Use different baselineKey values to maintain independent markets, brands, or campaigns.
Supported source fields
The normalizer accepts common aliases rather than requiring one vendor-specific export. Examples include:
| Canonical field | Accepted examples |
|---|---|
| Place ID | placeId, place_id, googlePlaceId |
| CID | cid, googleCid |
| Name | name, title, businessName, companyName |
| Address | address, fullAddress, formattedAddress, streetAddress |
| Rating | rating, totalScore, stars, averageRating |
| Reviews | reviewCount, reviewsCount, userRatingCount, numberOfReviews |
| Phone | phone, phoneNumber, telephone, phoneUnformatted |
| Website | website, websiteUrl, url, companyUrl |
| Coordinates | top-level latitude/longitude or nested location/coordinates |
| Hours | object or array forms under hours, openingHours, regularOpeningHours, workingHours |
| Timestamp | observedAt, scrapedAt, timestamp, capturedAt |
Rows missing a business name or containing invalid ratings, review counts, or coordinates are isolated as row errors. The run fails only when the configured invalid-row ratio is exceeded.
Entity matching
Matching is one-to-one and evidence-based:
- Exact Google Place ID
- Exact Google CID
- Strong normalized keys such as phone, domain, and name/address fingerprint
- Candidate-blocked fuzzy matching using business-name tokens, address similarity, and geographic distance
- Ambiguity rejection when two candidates are too close in score
A listing with a different explicit Place ID is never fuzzy-matched to another explicit Place ID. A shared chain website alone cannot match distant branches. Exact IDs are strongly recommended for the most reliable monitoring.
Output record
A qualified dataset item contains:
{"recordType": "alert","schemaVersion": 3,"alertId": "alert:...","entityId": "place:ChIJ-example-1","changeType": "UPDATED","competitorName": "Alpha Dental","severity": "high","impactScore": 78,"confidence": 0.71,"headline": "Alpha Dental changed reviewCount, rating and bookingUrl (high)","recommendedAction": "Compare review acquisition velocity and investigate the movement.","match": {},"changes": [],"metrics": {},"competitor": {"previous": {},"current": {}},"sourceUrl": null,"detectedAt": "2026-07-01T00:00:00.000Z","provenance": {}}
See sample-output/dataset.json for complete records generated from the bundled fixtures.
Pay-per-event behavior
The primary custom event is:
google-maps-competitor-change-tracker-result
One custom event is passed to Actor.pushData() for each alert that survives validation, matching, thresholds, severity filtering, and result limits. Invalid-row error items, when enabled, are pushed without the custom event. Pricing still has to be configured in Apify Console; pricing.example.json is deployment documentation, not proof that pricing is active.
Roadmap pricing:
- Launch: $10 per 1,000 qualified results
- Target: $15 per 1,000 qualified results
Local development
Requirements: Node.js 22 or newer.
npm cinpm run typechecknpm testnpm run samplesnpm run validateFORCE_LOCAL_RUNTIME=1 npm start
The local fallback writes Apify-compatible artifacts under storage/. On Apify, the Actor imports and uses the official apify SDK.
Safety and reliability
- Strict TypeScript with
noUncheckedIndexedAccess - Record and response-size limits
- Bounded retry count with exponential backoff and jitter
- Per-request timeout
- HTTPS-only URL imports
- Credential-bearing, localhost, private, and reserved targets rejected
- Redirect destinations revalidated before follow-up
- Deterministic deduplication, alert IDs, sorting, and matching
- No browser automation, login bypass, CAPTCHA bypass, or anti-bot evasion
- No API key required for default Store QA
- Baseline state is not advanced after a reported billing limit
Limitations
- The Actor analyzes structured snapshots; it does not collect Google Maps pages itself.
- Review velocity requires meaningful snapshot timestamps.
- Without Place ID or CID, matching is probabilistic and may reject ambiguous pairs rather than risk a false match.
- A missing listing means “not present in this snapshot,” not guaranteed business closure. Verify important removals.
- Scheduling, notifications, and webhooks are configured through Apify Platform around the Actor; they are not embedded notification providers.
- URL import allows public data only. Private network sources should be imported inline through an authorized upstream workflow.
Project files
ARCHITECTURE.md— product and engineering designSTORE_LISTING.md— publish-ready Store copyPRICING.md— event strategy and economicsDEPLOYMENT.md— cloud deployment checklistsample-output/— output generated by the real pipelineBUILD_REPORT.md,VALIDATION.md— generated build evidence in the final package
License
Apache-2.0. See LICENSE.