Appearance
Abandoned Booking Tracker
Overview
Capture customer contact data when they click "Book Now" — before Peek Pro's iframe opens. Save data progressively (field-by-field on blur) so even partial entries are captured. Then hand off to Peek for date/time selection and payment. Admin dashboard with CSV export for follow-up.
Extension type: Joomla Package (pkg_bookingtracker) — contains a System Plugin (frontend) + Admin Component (backend).
Phase 1: Foundation — Plugin Scaffold + Database
Goal: Installable Joomla plugin with database table, no UI yet.
Files to create:
plugins/system/bookingtracker/
bookingtracker.xml # Manifest (install config, DB schema ref)
services/provider.php # Joomla DI service provider
src/Extension/BookingTracker.php # Empty plugin class, registered events
sql/install.mysql.utf8.sql # CREATE TABLE #__bookingtracker_leads
sql/uninstall.mysql.utf8.sql # DROP TABLEDatabase table #__bookingtracker_leads:
idINT AUTO_INCREMENT PRIMARY KEYsession_idVARCHAR(64) — browser session cookiefull_nameVARCHAR(255)emailVARCHAR(255)phoneVARCHAR(50)party_sizeSMALLINTtour_urlVARCHAR(500) — Peek booking URLtour_nameVARCHAR(255) — tour name from link/pagepage_urlVARCHAR(500) — page where click happenedreferrerVARCHAR(500)utm_source,utm_medium,utm_campaignVARCHAR(100)ip_addressVARCHAR(45)statusENUM('partial','form_complete','booking_complete')created_atDATETIMEupdated_atDATETIMEcompleted_atDATETIMEpeek_booking_idVARCHAR(100)contactedTINYINT(1) DEFAULT 0notesTEXT
Done when: Plugin installs via Joomla admin, table is created, plugin appears in System plugins list.
Phase 2: Frontend Modal Form
Goal: "Book Now" clicks open our contact capture form instead of Peek's iframe.
Files to create:
media/plg_system_bookingtracker/
js/booking-form.js # Modal logic + progressive save
css/booking-form.css # Modal stylingFiles to modify:
BookingTracker.php— addonBeforeCompileHeadto inject JS/CSS on frontend pages
JS behavior (booking-form.js):
- On DOMContentLoaded, find all
a[data-embed="true"][href*="book.peek.com"] - Attach click listener that prevents default, opens modal
- Modal form: Full Name, Email, Phone, Party Size
- Each field saves via AJAX on
blur→ POST toindex.php?option=com_ajax&plugin=bookingtracker&format=json - "Continue to Booking" button closes modal, triggers Peek's original embed
- Auto-captures: tour URL (from href), tour name (from link text/heading), page URL, referrer, UTM params, session cookie
Done when: Clicking "Book Now" shows our modal. Filling in a name and tabbing away creates a partial lead in the DB. Clicking "Continue" opens Peek's iframe.
Phase 3: AJAX Backend — Save Leads
Goal: Plugin handles AJAX requests from the modal form.
Files to modify:
BookingTracker.php— addonAjaxBookingtrackermethod
AJAX actions:
action=create— creates new lead (on first field blur): stores session_id, tour_url, tour_name, page_url, referrer, UTMs, IP, status=partialaction=update— updates existing lead by session_id + tour_url: saves individual field values as they're enteredaction=complete_form— marks lead asform_completewhen "Continue to Booking" is clicked
Security:
- CSRF token validation (Joomla's
Session::checkToken) - Rate limiting by IP (prevent spam)
- Input sanitization on all fields
Done when: Progressive save works — each field blur updates the DB row. Admin can query #__bookingtracker_leads and see partial/complete entries.
Phase 4: Admin Component — Dashboard + Leads List
Goal: Admin panel to view, filter, and export captured leads.
Files to create:
administrator/components/com_bookingtracker/
bookingtracker.xml
services/provider.php
src/Extension/BookingTrackerComponent.php
src/Controller/DisplayController.php
src/Controller/LeadsController.php
src/Model/DashboardModel.php
src/Model/LeadsModel.php
src/View/Dashboard/HtmlView.php
src/View/Leads/HtmlView.php
tmpl/dashboard/default.php
tmpl/leads/default.phpDashboard view:
- Total leads count
- Breakdown by status (partial / form_complete / booking_complete)
- Abandonment rate (partial / total)
- Conversion rate (booking_complete / total)
- Top tours by interest (most clicked)
Leads list view:
- Table: Name, Email, Phone, Tour, Status, Date, Contacted
- Filters: date range, tour, status
- Sort by any column
- Pagination
CSV export:
- Export filtered leads as CSV download
- Columns: all lead fields
Bulk actions:
- Mark as contacted
- Delete selected
Done when: Admin can log in, see the dashboard, browse leads, filter, and download CSV.
Phase 5: Webhook — Track Completed Bookings
Goal: Mark leads as booking_complete when Peek confirms a booking.
Files to modify:
BookingTracker.php— add webhook handler toonAjaxBookingtracker
How it works:
- AJAX action
action=webhookreceives Peek'sbooking_updatePOST - Authenticates via shared secret (configurable in plugin params)
- Extracts tour/product info + booking reference from payload
- Correlates with existing leads by tour URL + time window (e.g., within 2 hours)
- Updates matching lead: status ->
booking_complete, storespeek_booking_id+completed_at
Done when: A completed Peek booking automatically marks the corresponding lead in our system.
Phase 6: Package + Deploy
Goal: Single installable ZIP for production.
Files to create:
pkg_bookingtracker.xml # Package manifest listing plugin + componentPackage contents:
plg_system_bookingtracker.zip— the plugincom_bookingtracker.zip— the admin componentpkg_bookingtracker.xml— package manifest
Deployment steps:
- Build ZIP locally
- Install on production via Administrator > System > Install > Extensions
- Enable the system plugin
- Configure webhook endpoint in Peek Pro
- Verify: click "Book Now" on live site -> modal appears -> data captured
Done when: Clean install on production, extension working end-to-end.
Reference
- Peek embed pattern:
<a href="https://book.peek.com/s/951f13c5-..." data-embed="true" data-button-text="Book Now"> - Peek webhook:
booking_updateevent (confirmed/updated/cancelled only) - Peek API docs: https://octodocs.peek.com
- Joomla plugin path:
plugins/system/bookingtracker/ - Joomla component path:
administrator/components/com_bookingtracker/ - DB prefix:
k8fo0_