Guest-reviews intelligence
Every review the portfolio earns lands on one board by morning, from every channel, already tied to the exact stay it came from.
Reputation was the most scattered data I had. Every property collected reviews on Booking.com, Expedia, Google, and TripAdvisor, each with its own login, its own rating scale, and its own inbox. Nobody read all of it across the portfolio, so a cleanliness dip at one property or a recurring front-desk complaint stayed invisible until it had already dragged down a score.
How it works
I built a Python client against MARA, a review API that already aggregates the whole portfolio. It is read-only, keyed by an X-API-Key header, with no server-side filtering, so the pull grabs every review group-wide, caches the last good full pull, and does all the property, date, and rating filtering in Python. The one hard rule is to aggregate only on the normalized mara_score, never the native rating, because Booking is out of 10 and Google is out of 5. It runs unattended on a dedicated Mac mini under launchd each morning and publishes a normalized board with themes and subratings.
The part I did not expect: each review carries a reservation_extras block with the room number, the check-in and check-out dates, the rate plan, and the PMS reservation ID. MARA has already resolved the OTA booking back to the exact room and stay, so I can join a review to a specific reservation without a single PMS API call.
The board is live and refreshes daily. The next layer, in progress, uses that same room-and-stay key to tie each cleanliness review back to the housekeeper who cleaned the room. That one stays gated. It touches employee data, and an adversarial audit showed the fairness logic (which clean gets credited, whether the guest even mentioned cleanliness) has to be hardened before any name goes next to a complaint.
This is the guest-services lead running as a cron job. Nobody reads all the reviews anymore, and the exceptions surface themselves.