The Astound Google Review Tracker is a Single Page Application (SPA) designed to track, visualize, and benchmark Google Review ratings for Astound Broadband locations across multiple regions. It uses a Serverless Architecture to securely fetch data from the Yext API while serving the frontend as static assets.
index.html: Main dashboard structure, styles, and embedded chart logic.dynamic.js: Handles data fetching, dashboard population, and region management.competitors.js: Stores static competitor benchmark data.Chart.js: For rendering trend graphs and rankings.jsPDF / html2canvas: For export functionality.serverless-function/netlify/functions/yext-proxy.js: Production proxy for Yext API calls.
cloud-function/main.py: Alternative Python-based proxy (Cloud Function).index.html loads.dynamic.js and competitors.js are executed.window.REGIONS is initialized with location metadata (Entity IDs, Addresses).dynamic.js calls populateDashboard().GET /.netlify/functions/yext-proxy?entityId={ID}&maxDate={DATE}
yext-proxy.js) receives the request.GET https://api.yextapis.com/v2/accounts/me/reviews
dynamic.js parses the rating.competitors.js injects hardcoded benchmark data (Xfinity, Spectrum, etc.) into the grid
alongside live Astound data.sequenceDiagram
participant User
participant Browser (dynamic.js)
participant Proxy (Netlify Function)
participant YextAPI
participant StaticData (competitors.js)
User->>Browser: Opens Dashboard
Browser->>StaticData: Load Competitor Data (Hardcoded)
Browser->>Browser: Render Dashboard Structure
loop For Each Location & Month
Browser->>Proxy: Fetch Rating (EntityID, Date)
Proxy->>YextAPI: Request Review Data (with Secret Key)
YextAPI-->>Proxy: Return JSON Data
Proxy-->>Browser: Return JSON Data
Browser->>Browser: Update Table Cell
end
Browser->>User: Display Full Report
graph TD
%% Nodes
Browser[("Browser / Dashboard\n(User Interface)")]
StaticData[("Static Files\n(Competitors.js & Locations)")]
Proxy[("Netlify Serverless Function\n(Security Layer)")]
Yext[("Yext API\n(Live Astound Reviews)")]
%% Styles
style Browser fill:#f9f,stroke:#333,stroke-width:2px
style StaticData fill:#eee,stroke:#333,stroke-width:1px
style Proxy fill:#bbf,stroke:#333,stroke-width:1px
style Yext fill:#bfb,stroke:#333,stroke-width:1px
%% Connections
Browser -- "1. Loads hardcoded data directly" --> StaticData
Browser -- "2. Requests review data" --> Proxy
Proxy -- "3. Authenticates with API Key" --> Yext
Yext -- "4. Returns live ratings" --> Proxy
Proxy -- "5. Returns data to dashboard" --> Browser
| Data Type | Source | Implementation Details |
|---|---|---|
| Astound Reviews | Yext API | Fetched dynamically via yext-proxy. Requires entityId. |
| Competitor Reviews | Static File | Hardcoded in competitors.js (variable COMPETITOR_MAPPINGS).
Does NOT currently use Google Maps API. |
| Locations | Static File | Defined in dynamic.js (variable REGIONS). |
CRITICAL: There are several locations where API keys are defined. For the application to work securely and correctly, you must update these locations or ensure Environment Variables are set.
Used to authenticate with Yext to get review data.
Production (Netlify Function):
serverless-function/netlify/functions/yext-proxy.jsconst YEXT_API_KEY = process.env.YEXT_API_KEY || "a4b10...";
YEXT_API_KEY in Netlify Site Settings.
Warning: The current code contains a hardcoded fallback key that should be removed for
security.
Alternative (Google Cloud Function):
cloud-function/main.pyYEXT_API_KEY = "a4b10..."Frontend (Legacy/Dev):
dynamic.jsconst YEXT_API_KEY = "YOUR_YEXT_API_KEY_HERE";Intended for fetching competitor data, but currently unused by the active logic.
competitors.jsconst GOOGLE_MAPS_API_KEY = "YOUR_GOOGLE_MAPS_API_KEY_HERE";
COMPETITOR_MAPPINGS on line 9).competitors.js
must be rewritten to actually fetch data using this key.Edit dynamic.js and modify the REGIONS object.
'Texas': {
manager: 'Name',
locations: [
{ address: '...', city: '...', entityId: 'NEW_ID' }
]
}
Edit competitors.js and manually update the ratings in COMPETITOR_MAPPINGS.
'City-State': {
verizon: { address: '...', rating: 4.5 }, // Update this value
// ...
}