Start here
Each flow is written the same way: what starts it, what happens in order, the emails it sends, where to see proof it happened, and how to switch it off. Every step carries one of these tags:
The short version
Almost nothing runs on our own servers. The work happens inside Zoho (CRM, Billing, Books, Commerce, POS, Checkout, Flow, Forms, Backstage, Creator, Cliq) and GolfManager. Zoho Flow is the switchboard: it catches an event in one system and runs a small piece of code that writes to another.
Who holds what
GolfManager is where customers book and where credits are spent. Zoho Billing runs memberships and card charges. Zoho Books holds every invoice. Zoho CRM is the customer record and sends most of our emails.
Where the detail lives
Code and the automation inventory are in the Max AI OS folder under references/automation-estate-handover/. The research behind each flow is in references/systems-handbook/traces/.
System map
Which systems each flow touches. Open a flow for the step-by-step.
| Flow | Website | Zoho Forms | Zoho Checkout | Zoho Commerce | Zoho POS | Zoho Billing | Zoho Books | Zoho Flow | Zoho CRM | GolfManager | Zoho Backstage | Zoho Creator | Zoho Cliq | Meta | Google Ads / GA4 | Zoho Bookings | Zoho Recruit | Referral Factory | Zoho Desk | Marketing Automation | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Google Ads | |||||||||||||||||||||
| Meta Ads | |||||||||||||||||||||
| Website paths | |||||||||||||||||||||
| Game Plan tools | |||||||||||||||||||||
| New lead | |||||||||||||||||||||
| Evaluation booked | |||||||||||||||||||||
| Sales pipeline | |||||||||||||||||||||
| Referral | |||||||||||||||||||||
| Online store | |||||||||||||||||||||
| Desk sale (POS) | |||||||||||||||||||||
| Membership signup | |||||||||||||||||||||
| Lesson booking | |||||||||||||||||||||
| No-show | |||||||||||||||||||||
| Lesson report | |||||||||||||||||||||
| Member event | |||||||||||||||||||||
| Coach Area | |||||||||||||||||||||
| PAYG follow-ups | |||||||||||||||||||||
| Monthly renewal | |||||||||||||||||||||
| Annual renewal and card expiry | |||||||||||||||||||||
| Payment failure | |||||||||||||||||||||
| Retention and at-risk | |||||||||||||||||||||
| Pause or cancel | |||||||||||||||||||||
| Reviews | |||||||||||||||||||||
| Who got an email | |||||||||||||||||||||
| Facility issues and feedback | |||||||||||||||||||||
| Reports and digests | |||||||||||||||||||||
| Recruitment | |||||||||||||||||||||
| Cliq alerts | |||||||||||||||||||||
| Zoho Bookings sync |
All flows
Grouped by where the customer is in their journey.
Marketing and the website
Winning customers
Buying
Coaching and visits
Keeping members
Team and channels
All flows › Google Ads
When someone clicks a Google Ad
Google Ads clicks land with UTM tags that feed CRM leads and Google Ads' own conversion reporting via Supermetrics and GA4.
- Starts when
- A person clicks a Google Ads Search, Display, Video or Performance Max ad for SwingFIT and lands on swingfitacademies.com.
- Covers
- Covers a paid Google Ads click (Search or Performance Max) landing on swingfitacademies.com through to a Lead/Evaluation_Booking record in Zoho CRM, GA4/GTM tracking, conversion import back into Google Ads, and Supermetrics reporting. Does not cover organic Google traffic or the coaching/booking journey after the lead is created.
- Systems
- Google Ads, GA4 / GTM, Website, Zoho CRM, Zoho Bookings, Zoho Checkout, GolfManager, Supermetrics
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Ad clickGoogle Ads
Ad click carries tracking parameters to the landing page
Verified liveCloudstons (the Google Ads agency) manages one Google Ads account with campaigns
GOOG_SEARCH_MULTI_ALL_EVERGREEN,GOOG_DISPLAY_MULTI_ALL_RT_EVERGREENandGOOG_VIDEO_MULTI_ALL_RT_EVERGREEN. An account-level Tracking Template appends utm_source=google, utm_medium (cpc/pmax/display/video), utm_campaign={campaignid}, utm_content={creative}, utm_term={keyword}, utm_id={campaignid} and utm_lead_source=google_ads to the destination URL, and Google Auto-tagging appends the gclid separately.See itGoogle Ads → Admin → Account settings → Tracking → Tracking Template - T+0Page loadWebsite
Landing page loads with GA4/GTM tracking
Unverifiedswingfitacademies.com runs a Google Tag Manager container that fires GA4 page_view/session_start events, capturing the UTM parameters and gclid into the GA4 property that feeds BigQuery and Supermetrics.
See itGTM container / GA4 DebugView on a live click-through - T+secondsForm submitWebsite
Visitor submits a lead or evaluation-booking form
Verified liveThe visitor fills in the swingfitacademies.com lead form or evaluation booking form. The form carries the page's current UTM_Source/UTM_Medium/UTM_Campaign/UTM_Content/UTM_Term/utm_lead_source values into the new
LeadsorEvaluation_Bookingrecord it creates in Zoho CRM.See itCRM → Leads or Evaluation_Booking → record → UTM fields - T+0First touchZoho CRM
First-touch date is stamped
From codeSet First Touch Date(workflow rule on Leads, create trigger) stamps a first-touch timestamp field on the new lead.See itCRM → Setup → Automation → Workflow Rules → Leads - T+0Source & channelZoho CRM
Lead source and lead channel are worked out from the UTM fields
UnverifiedLeadSourceAssignment_1(actionGoogleAdsLeadSourceAssignment) is designed to set Lead_Source to Google Ads when Lead_Source is empty and UTM_Source contains "google" and UTM_Medium contains "cpc".Set Lead Channel – Google Adsis designed to set Lead_Channel the same way;Set Lead Channel – Google Organicis designed to set it when UTM_Medium contains "organic".See itCRM → Setup → Automation → Workflow Rules → Leads - T+0Owner assignedZoho CRM
Lead is routed to a salesperson
From codeAssign Lead Ownerassigns the new lead to a sales rep via the standard owner-assignment rule.See itCRM → Leads → record → Lead Owner - T+secondsAuto-replyZoho CRM
Lead gets an immediate reply and staff are notified
UnverifiedsfaSpeedleadAutoReply TriggerfiressfaSpeedleadAutoReply, andNEW LEAD - Email/New Lead WA Notifysend an internal notification email and WhatsApp message so staff can follow up fast.See itCRM → contact → Emails; staff WhatsApp/Cliq notification - laterBooking & paymentZoho Bookings
Booking and payment can move across separate domains
UnverifiedWhen the lead books an evaluation or pays, the journey can move through zohobookings.com and zohosecurepay.com (payment) before the session is created in GolfManager (asia.golfmanager.com) — each a separate domain from swingfitacademies.com and from each other.
See itn/a - dailyReporting pullGA4 / GTM
Performance data is pulled into reporting
Verified liveSupermetrics connects to the Google Ads account (
SwingFIT Academies, account 9706158917) and to GA4, and reports campaign spend, clicks and conversions for the team.See itSupermetrics dashboard / Google Ads UI → Campaigns - ongoingConversions importedGoogle Ads
Conversions are imported back into Google Ads
Verified liveGoogle Ads' conversion actions blend on-site click signals (Book Evaluation Click, Book My Intro To Golf – Click, Book Now Click (Membership)) with GA4-sourced conversions (Purchase (Google Analytics event purchase), Submit Lead Form, Submit Membership Lead Form, Evaluation Confirmation, Intro To Golf Confirmation, Trial Booking (2)) and a WhatsApp Contact conversion, feeding Smart Bidding.
See itGoogle Ads → Goals → Conversions - T+2 minOffline importZoho CRM
Paid evaluation bookings from a Google ad are sent back to Google Ads
From codeTwo minutes after a paid evaluation booking (Source = App) is saved as Confirmed, the function
sfaGoogleOfflineSchedulechecks for a Google click id (GCLID). If there is one, it adds a row to the import Google Sheet (conversion 'Evaluation Confirmation (Server)', AED 99). Google Ads Data Manager imports that sheet once a day. Bookings without a GCLID are skipped. Every run leaves a 'Google sheet test result' note on the booking.See itCRM → Evaluation_Booking → record → Notes ('Google sheet test result'); Google Ads → Goals → Conversions → Evaluation Confirmation (Server)
Emails and messages
TeamNEW LEAD - EmailUnverifiedNew Lead notification
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did this Google lead get credited correctly? | CRM lead record → Lead_Source and Lead_Channel fields | Lead_Source = Google Ads and Lead_Channel = Google Ads/Google Organic |
| Is the Google Ads tracking template still correct? | Google Ads → Admin → Account settings → Tracking | Resolved URL contains utm_source, utm_medium, utm_campaign, utm_content, utm_id, utm_lead_source with no spaces or pipes |
| Are conversions still importing? | Google Ads → Goals → Conversions | Each conversion action shows recent activity in its Status column |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Google Ads tracking template | Google Ads → Admin → Account settings → Tracking | UTM parameters stop being appended to ad click-throughs; leads still reach CRM but without source detail |
| LeadSourceAssignment_1 / Set Lead Channel rules | CRM → Setup → Automation → Workflow Rules → Leads | Lead_Source/Lead_Channel stop auto-filling for Google traffic |
| Function sfaGoogleOfflineSchedule (scheduled action on rule sfaMetaCapiSchedule) | CRM → Setup → Automation → Workflow Rules → Evaluation_Booking | Google-click evaluation bookings stop being written to the import sheet |
Good to know
Two agencies, two platforms
Cloudstons manages the Google Ads account; Renue manages the Meta ad account. Each follows its own URL-tagging template in the SwingFIT UTM Standard v1.1.
ID-based UTMs
Campaign, ad and keyword UTM values resolve to numeric IDs rather than names, so BigQuery/Supermetrics join them back to human-readable names via the Google Ads connector.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (9)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
LeadSourceAssignment_1 (GoogleAdsLeadSourceAssignment)6296422000042039003 | workflow rule | Active last run 2026-07-24T09:28 | Leads create or edit Lead_Source is empty AND UTM_Source contains 'google' AND UTM_Medium contains 'cpc' | Sets Lead_Source field to Google Ads. | CRM → Setup → Automation → Workflow Rules → Leads $HOME/arch/raw_capture/rules_all.jsonl (rule 6296422000042039003) |
Set Lead Channel – Google Ads6296422000032987765 | workflow rule | Active last run 2026-10-08T07:31 | Leads create or edit UTM_Source contains 'google' AND UTM_Medium contains 'cpc' | Field update sets Lead_Channel to Google Ads. | CRM → Setup → Automation → Workflow Rules → Leads $HOME/arch/raw_capture/rules_all.jsonl (rule 6296422000032987765) |
Set Lead Channel – Google Organic6296422000032987786 | workflow rule | Active | Leads create or edit UTM_Source contains 'google' AND UTM_Medium contains 'organic' | Field update sets Lead_Channel to Google Organic. | CRM → Setup → Automation → Workflow Rules → Leads $HOME/arch/raw_capture/rules_all.jsonl (rule 6296422000032987786) |
Set First Touch Date6296422000032987706 | workflow rule | Active last run 2026-10-10T21:09 | Leads create none (all new leads) | Field update stamps a first-touch timestamp field. | CRM → Setup → Automation → Workflow Rules → Leads $HOME/arch/estate.txt (automation index) |
Assign Lead Owner6296422000016357005 | workflow rule | Active | Leads create unspecified in archive summary | Assign-owner action routes the lead to a sales rep. | CRM → Setup → Automation → Workflow Rules → Leads $HOME/arch/estate.txt (automation index) |
sfaSpeedleadAutoReply | function | Inactive | sfaSpeedleadAutoReply Trigger (Leads, create) unspecified in archive summary | Sends a fast auto-reply to the new lead. | CRM → Setup → Automation → Functions crm_functions_live/functions/sfaSpeedleadAutoReply.deluge |
NEW LEAD - Email6296422000001597020 | workflow rule | Inactive last run 2026-09-08T13:26 | Leads create none (all new leads) | Sends an internal notification email to staff. | CRM → Setup → Automation → Workflow Rules → Leads $HOME/arch/estate.txt (automation index) |
New Lead WA Notify6296422000006965001 | workflow rule | Inactive last run 2026-09-08T13:26 | Leads create or edit unspecified in archive summary | Sends an internal WhatsApp notification to staff. | CRM → Setup → Automation → Workflow Rules → Leads $HOME/arch/estate.txt (automation index) |
sfaGoogleOfflineSchedule6296422000055866019 | function | Active | Workflow rule sfaMetaCapiSchedule (scheduled action, 2 minutes after the booking qualifies) Status = Confirmed, Source = App, name not containing member/intro, Player set, GCLID present (GCLID-only since 2026-10-13, Max) | Appends one row (GCLID, 'Evaluation Confirmation (Server)', Dubai conversion time, 99, AED, hashed email, hashed phone, sfa-eval-<bookingId>, bookingId) to the live import Google Sheet via Zoho connection sfagsheets. Google Ads Data Manager imports that sheet daily as an offline conversion. Writes a 'Google sheet test result' note on the booking every run. | CRM → Setup → Developer Hub → Functions SwingFIT AI OS/crm_functions_live/functions/sfaGoogleOfflineSchedule.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Leads | UTM_Source | Ad platform reported by the tracking template (e.g. google, meta, referral_factory). | Landing-page form querystring capture |
| Leads | UTM_Medium | Ad medium reported by the tracking template (e.g. cpc, pmax, organic). | Landing-page form querystring capture |
| Leads | UTM_Campaign | Numeric campaign ID. | Landing-page form querystring capture |
| Leads | Lead_Source | Picklist attribution field used across reporting. | LeadSourceAssignment_1 and related source-assignment rules |
| Leads | Lead_Channel | Picklist attribution field distinguishing paid vs organic within a source. | Set Lead Channel – * rules |
| Evaluation_Booking | GCLID | Google click id captured on the booking; the only match key for the offline import. | Booking form querystring capture |
Full email text
NEW LEAD - EmailNew Lead notification
IDs and references
| What | Value |
|---|---|
| Google Ads account (Supermetrics) | 9706158917 |
| Google Ads Search campaign ID | 23618939712 |
| Google Ads Display campaign ID | 23693851180 |
| Google Ads Video campaign ID | 23734535708 |
| Zoho CRM org | 866442566 |
All flows › Meta Ads
When someone clicks or submits a Meta ad
Meta ad clicks and lead-ad submissions create CRM records and echo conversion events back to Meta's pixel via server-side APIs.
- Starts when
- A person clicks a Meta (Facebook/Instagram) ad for SwingFIT, or fills in a native Meta Lead Ad form.
- Covers
- Covers a paid Meta (Facebook/Instagram) ad click or a native Meta Lead Ad submission through to a Lead/Evaluation_Booking record in Zoho CRM, the Meta pixel and server-side Conversions API events sent back to Meta, and how leads are attributed in CRM. Does not cover organic social posts.
- Systems
- Meta, Website, Zoho CRM, Zoho Flow, Zoho Bookings, Zoho Checkout, Zoho Billing, Zoho POS, GolfManager
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Ad clickMeta
Ad click carries tracking parameters to the landing page
From codeRenue (the Meta ads agency) manages the SwingFIT Academies Meta ad account (act_1625681971960672). Each ad's URL Parameters field (set per ad — Meta has no account-level template) carries: utm_source=meta, utm_medium=paid_social (paid_video for Reels), utm_campaign=campaign.id, utm_content=ad.id, utm_term=adset.id, utm_id=campaign.id, utm_lead_source=meta_ads, platform=site_source_name, placement=placement.
See itAds Manager → Ad → Tracking → URL Parameters - T+0Pixel firesMeta
Meta Pixel fires on the landing page
Verified liveThe Meta Pixel (dataset
SFA Pixel 2026, id 4473134646297796) fires PageView and InitiateCheckout events from the browser as the visitor lands and moves through the funnel.See itEvents Manager → Data Sources → SFA Pixel 2026 - T+secondsForm or Lead AdWebsite
Visitor submits a lead or evaluation-booking form, or a native Meta Lead Ad
Verified liveEither the visitor fills the swingfitacademies.com form (creating a Leads/Evaluation_Booking record with the UTM fields above), or fills a native Meta Lead Ad form, which Meta pushes into CRM. The workflow rule
Leads_ZohoFlow_ZCRM - Meta(a Zoho Flow webhook, active) is the CRM side of that native sync.See itCRM → Leads → record → UTM fields, or CRM → Setup → Automation → Workflow Rules → Leads - T+0Lead channelZoho CRM
Lead channel is worked out from the UTM fields
UnverifiedSet Lead Channel – Facebookis designed to set Lead_Channel when UTM_Source contains "facebook";Set Lead Channel – Instagramis designed to set it when UTM_Source contains "instagram".See itCRM → Setup → Automation → Workflow Rules → Leads - T+0CRM → Meta (lead)Zoho CRM
Lead is echoed back to Meta as a CompleteRegistration event
From codeZcrm_to_Meta(Zoho Flow function on the CRM lead webhook) checks the lead's Lead_Source field; if it equals "Meta_Ads" it hashes the lead's email/phone and posts aCompleteRegistrationserver-side event to the Meta Conversions API for pixel 4473134646297796.See itEvents Manager → SFA Pixel 2026 → Test events / Overview - T+0CRM → Meta (eval)Zoho CRM
Paid evaluation bookings are sent to Meta as a Schedule event
Verified liveWhen a paid evaluation booking (Source = App) is saved as Confirmed, the workflow rule
sfaMetaCapiScheduleruns the function of the same name. It sends oneScheduleevent worth AED 99 to the Meta Conversions API for pixel 4473134646297796, matched on the player's hashed email and phone plus the Meta click id (FBCLID) when the booking came from a Meta ad. Member evaluations and Intro to Golf bookings are skipped. Every run leaves a 'Meta CAPI test result' note on the booking.See itCRM → Evaluation_Booking → record → Notes ('Meta CAPI test result'); Events Manager → SFA Pixel 2026 → Overview - ongoingOther CAPI feedsZoho Flow
Purchases, subscriptions, checkouts and bookings are echoed back to Meta from other systems
From codeFive more Flow functions post server-side conversion events to the same pixel from other systems:
ZBookingsEventBooked_to_MetaCAPI(Bookings),Zcheckout_to_Meta(Checkout),Zsubscription_to_meta(Billing subscriptions),ZPOS_commerce_to_Meta(POS/Commerce) and a billing-side function. Two different access tokens are hardcoded across these functions.See itn/a (Zoho Flow function source) - weeklyQuality reviewMeta
Dataset quality and campaign performance are monitored
Verified liveRenue and Max review campaign performance in Ads Manager and event-match-quality for the SFA Pixel 2026 dataset in Events Manager.
See itEvents Manager → SFA Pixel 2026 → Diagnostics
Emails and messages
TeamNEW LEAD - EmailUnverifiedNew Lead notification
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did this Meta lead get credited correctly? | CRM lead record → Lead_Source and Lead_Channel fields | Lead_Source = Meta_Ads and Lead_Channel = Facebook or Instagram |
| Is the pixel still receiving events? | Events Manager → SFA Pixel 2026 → Diagnostics | Event match quality scores present with hourly/real-time upload frequency for PageView and InitiateCheckout |
| Are all six Meta CAPI functions still needed? | Zoho Flow → Zoho - Meta folder | Each function's linked flow is enabled and has a recent execution |
| Was this evaluation booking sent to Meta? | CRM → Evaluation_Booking → record → Notes | A 'Meta CAPI test result' note with testMode=false and events_received=1 |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Ad-level URL Parameters | Ads Manager → Ad → Tracking → URL Parameters | UTM tags stop being appended to that ad's click-throughs |
| Set Lead Channel – Facebook/Instagram rules | CRM → Setup → Automation → Workflow Rules → Leads | Lead_Channel stops auto-filling for Meta traffic |
| Zcrm_to_Meta function | Zoho Flow → Zoho - Meta folder | CompleteRegistration events for leads stop being sent to Meta |
| Workflow rule sfaMetaCapiSchedule | CRM → Setup → Automation → Workflow Rules → Evaluation_Booking | Paid evaluation bookings stop being sent to Meta (and to the Google import sheet) |
Good to know
Four ad accounts, one live
The Meta connection shows four accessible ad accounts; only 'SwingFIT Academies 2.0' (act_1625681971960672) currently has active campaigns.
Server-side plus browser-side
SwingFIT sends both browser Pixel events and server-side Conversions API events for the same actions — the redundancy setup Meta recommends for match quality.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (11)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Set Lead Channel – Facebook6296422000032987744 | workflow rule | Active | Leads create or edit UTM_Source contains 'facebook' | Field update sets Lead_Channel to Facebook. | CRM → Setup → Automation → Workflow Rules → Leads $HOME/arch/raw_capture/rules_all.jsonl (rule 6296422000032987744) |
Set Lead Channel – Instagram6296422000032987723 | workflow rule | Active | Leads create UTM_Source contains 'instagram' | Field update sets Lead_Channel to Instagram. | CRM → Setup → Automation → Workflow Rules → Leads $HOME/arch/raw_capture/rules_all.jsonl (rule 6296422000032987723) |
Leads_ZohoFlow_ZCRM - Meta6296422000042060001 | workflow rule | Active last run 2026-10-11T08:46 | Leads create or edit none | Webhook action forwarding lead data into a Zoho Flow that syncs Meta native Lead Ads into CRM. | CRM → Setup → Automation → Workflow Rules → Leads (read-only, Flow-managed) $HOME/arch/raw_capture/rules_all.jsonl (rule 6296422000042060001) |
Zcrm_to_Meta | function | Unknown | Lead create/edit webhook (leadID param) Lead_Source == 'Meta_Ads' | Hashes lead email/phone (SHA-256), posts a CompleteRegistration event to graph.facebook.com/v25.0/{pixel_id}/events for pixel 4473134646297796; fbc/fbp/ua are hardcoded empty strings. | Zoho Flow → Zoho - Meta → ZCRM - Meta $HOME/arch/flow_deluge_source/Zcrm_to_Meta.deluge |
sfaMetaCapiSchedule6296422000055764052 | workflow rule | Active last run 2026-10-12 | Evaluation_Booking create or edit (fires once per record when criteria are first met; repeat off) Source = App AND Status = Confirmed | Instant: runs function sfaMetaCapiSchedule (Meta). Scheduled +2 min: runs function sfaGoogleOfflineSchedule (Google sheet). Trigger changed 2026-10-12 from field-update to create-or-edit, because bookings are created already Confirmed. | CRM → Setup → Automation → Workflow Rules → Evaluation_Booking SwingFIT AI OS/crm_functions_live/functions/ (rule read back live 2026-10-12) |
sfaMetaCapiSchedule6296422000055764047 | function | Active last run 2026-10-12T17:37 | Workflow rule sfaMetaCapiSchedule (instant action), or run by hand with bookingId Status = Confirmed, Source = App, booking name not containing member/intro, Player set | Sends one 'Schedule' event (value 99 AED, event_id sfa-eval-<bookingId>, action_source system_generated) to the Meta Conversions API for pixel 4473134646297796, with hashed email + phone and fbc built from the booking's FBCLID and created time. Token/version/test code from org variables (never hardcoded). Writes a 'Meta CAPI test result' note on the booking every run (including skips) showing has_em/has_ph/fbc and Meta's response. Replaces the old Flow EvaluationBookingZCRM_Meta. | CRM → Setup → Developer Hub → Functions SwingFIT AI OS/crm_functions_live/functions/sfaMetaCapiSchedule.deluge |
EvaluationBookingZCRM_Meta | function | Switched | Evaluation_Booking create/update (EvalBookingID param) UTM_Source == 'meta_ads' (exact match) | Hashes player email/phone, posts a schedule event to the Meta Conversions API for pixel 4473134646297796; fbc/fbp/ua are hardcoded empty strings. | Zoho Flow → Zoho - Meta → EvaluationBookingZCRM - Meta $HOME/arch/flow_deluge_source/EvaluationBookingZCRM_Meta.deluge |
ZBookingsEventBooked_to_MetaCAPI | function | Draft/paused | Zoho Bookings event booked (bookingID param) unspecified in archive summary | Posts a booking conversion event to the Meta Conversions API. | Zoho Flow → Zoho - Meta → ZBookings - Meta $HOME/arch/flow_deluge_source/ZBookingsEventBooked_to_MetaCAPI.deluge |
Zcheckout_to_Meta | function | Draft/live | Zoho Checkout payment (paymentID, Email, phone params) unspecified in archive summary | Posts a checkout/purchase conversion event to the Meta Conversions API. | Zoho Flow → Zoho - Meta → ZCheckout - Meta $HOME/arch/flow_deluge_source/Zcheckout_to_Meta.deluge |
Zsubscription_to_meta | function | Draft/live | Zoho Billing subscription event (SubscriptionID, orgID params) unspecified in archive summary | Posts a subscription conversion event to the Meta Conversions API. | Zoho Flow → Zoho - Meta → ZSubscription - Meta $HOME/arch/flow_deluge_source/Zsubscription_to_meta.deluge |
ZPOS_commerce_to_Meta | function | Wired | POS/Commerce webhook (invoiceID, inc_org_id params) unspecified in archive summary | Intended to post a purchase conversion event to the Meta Conversions API from POS/Commerce sales. | Zoho Flow → Zoho - Meta → ZPOS/Commerce - Meta $HOME/arch/flow_deluge_source/ZPOS_commerce_to_Meta.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Leads | UTM_Source | Ad platform reported by the tracking template (e.g. meta, fb, ig historically). | Landing-page form querystring capture, or Meta native Lead Ad sync |
| Leads | Lead_Source | Picklist attribution field used across reporting; drives Zcrm_to_Meta's CAPI condition. | Source-assignment workflow rules |
| Leads | Lead_Channel | Picklist attribution field distinguishing Facebook vs Instagram within Meta. | Set Lead Channel – Facebook / Instagram rules |
| Evaluation_Booking | UTM_Source | Ad platform reported at time of booking; drives EvaluationBookingZCRM_Meta's CAPI condition. | Booking form querystring capture |
| Evaluation_Booking | FBCLID | Meta click id captured on the booking; becomes fbc in the server-side Schedule event. | Booking form querystring capture |
Full email text
NEW LEAD - EmailNew Lead notification
IDs and references
| What | Value |
|---|---|
| Meta ad account (active) | act_1625681971960672 (SwingFIT Academies 2.0) |
| Meta ad account (secondary) | act_3241955282798636 (OGP #1) |
| Meta pixel / dataset | 4473134646297796 (SFA Pixel 2026) |
| Meta pixel / dataset (legacy) | 843299620709765 (SwingFIT Store Pixel) |
| Meta business | 1051146055547681 (Swingfit academies) |
All flows › Website paths
How the website sends people to the right place
Maps every main call-to-action on swingfitacademies.com to where it actually sends a visitor, and how the site itself is deployed.
- Starts when
- A visitor on swingfitacademies.com (WordPress + Elementor, hosted on Hostinger) clicks a call-to-action button or link.
- Covers
- Covers the live public site's main pages and every call-to-action path: evaluation booking, buying a pack, memberships, member events, booking lessons, referral, forms, WhatsApp, and the tracking tags present on pages. Does not cover what happens after a booking/payment lands in GolfManager or CRM (see
eval-booking-payment-to-mrr-funnel,membership-signup,pos-sale) or the Game Plan Builder/roadmap/check-in tools (seegame-plan-tools). - Systems
- Website, Zoho Bookings, Zoho Commerce, GolfManager, Zoho Backstage, Referral Factory, Zoho CRM, WhatsApp, GA4 / GTM, Meta
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Click 'Book my evaluation'Website
Book an evaluation routes through a link shortener to Zoho Bookings
UnverifiedThe evaluation CTA on
/golf-swing-evaluation/and/membership/is designed to send a visitor to a bookable slot on Zoho Bookings via a short link (zbooking.us/FaNfO). Followed live, the link currently lands on the general Zoho Bookings page rather than a specific slot picker.See itcurl -IL http://zbooking.us/FaNfO from a terminal and read the Location headers; or click the button and watch the address bar - T+0Click a pack/product linkWebsite
Buying a pack (PAYG lesson packs, practice passes, play sessions) goes to Zoho Commerce
Verified live/payg/and related pages link each individual product (e.g.8 x 60-min beginner golf lesson,Play - 9 holes,Birdie/Eagle/Par Creditpacks) straight to its own product page onstore.swingfitacademies.com, SwingFIT's Zoho Commerce storefront. Each product is its own URL/id, so there is no single 'store' landing page — every pack has its own direct link from the pricing page.See itLoad/payg/and hover any package button; the destination host isstore.swingfitacademies.com/products/... - T+0Click 'Book' in the header / consumer shopWebsite
Booking lessons or paying for an existing package goes to GolfManager's own booking portal
Verified liveThe site header's main booking button, and a 'consumer shop' link on
/payg/, point athttps://asia.golfmanager.com/swingfit(GolfManager's public tenant portal), with the pricing page's specific link going to.../consumer/shop?tab=1. This is GolfManager's own hosted booking/shop UI, separate from the WordPress site and separate from Zoho Commerce.See itHeader 'Book' button and/payg/'consumer shop' link both resolve toasia.golfmanager.com/swingfit - T+0Visit /membership/Website
The membership page sells membership with the same booking links as the evaluation page
Verified live/membership/carries no distinct membership checkout of its own on this site visit — its calls to action are the samezbooking.us/FaNfOshortener and the GolfManager portal link seen on the evaluation page. Membership sign-up/billing itself is handled off-site once a coach or the sales process moves someone to a Billing hosted page (not reachable from a public page link on this pass).See itLoad/membership/and inspect its two outbound buttons - T+0Click a member eventWebsite
Member events route to Zoho Backstage
Verified live/member-events/lists individual group classes/clinics, each linking directly toevents.swingfitacademies.com/<EventSlug>— Zoho Backstage's public event page for that event. Backstage also offers an embeddable 'Register now' modal widget (window.ZBSCheckOutWidget._createWidget, loaded fromstatic.zohocdn.com) that can open registration in an overlay instead of navigating away, keyed off the sameevents.swingfitacademies.com/embed/<slug>/buyTicketsURL pattern; the live/member-events/page uses plain links to the Backstage page rather than the embedded widget.See itLoad/member-events/and hover an event card; destination host isevents.swingfitacademies.com - n/aReferral link sharedWebsite
Referral runs on a separate platform, shared manually rather than linked from the site
Verified liveThe referral programme runs on Referral Factory at
refer.swingfitacademies.com/<campaign-code>. It is not linked from the live site's navigation, footer, or any page checked on this pass — Member Success or a coach sends the link directly to a member (WhatsApp/email) at a chosen moment, and the member gets their own personal referral link from that landing page.See itSearch the live site's nav/footer/pages for 'refer.swingfitacademies.com' (not found); the link is sent by staff instead - T+0Submit the contact formWebsite
The Contact page form goes to the support desk, not the sales CRM
Verified live/contact/'s form posts todesk.zoho.com/support/WebToCase— a Zoho Desk support-ticket form, not a Zoho Forms-to-CRM lead form. A separate WhatsApp link (wa.me/971506926003) sits on the same page as an alternative.See itView source on/contact/and find the form'saction=attribute - T+0 to T+~1sSubmit the homepage 'Get your roadmap' quizWebsite
The homepage's own roadmap quiz is the one on-page form that writes into the sales CRM
Verified liveThe three-question quiz on the homepage posts name/email/goal/level/commitment to
sfa-roadmap-capture.php, which calls CRM functionsfaRoadmapCaptureto create aPlayer_Roadmaprecord (RM-prefix) and match/create the person as a Lead or Contact. The quiz's own on-page result, however, scrolls to a#pricinganchor rather than sending the visitor anywhere new.See itPlayer_Roadmap records withRoadmap_IDstartingRM-,Source = Website - T+0Click the WhatsApp iconWebsite
WhatsApp is available as a direct link and a floating chat widget
Verified liveA direct
wa.me/971506926003link appears on the Contact page; the wider site also loads an Elfsight-based floating chat widget available site-wide.See itView source forwa.meandelfsightreferences on any page - T+0Any page loadWebsite
Every page carries Google Tag Manager, GA4 and the Meta pixel
Verified liveGoogle Tag Manager container
GTM-N765MP89loads on every page (confirmed via the iframe fallback and thegoogletagmanager.com/gtag(script), alongside a Meta Pixel (fbq() call andconnect.facebook.net. GTM is the mechanism by which GA4 and any other page tags fire, so most on-page tracking changes are made in GTM rather than hardcoded per page.See itView source on any live page forGTM-N765MP89,fbq(,connect.facebook.net - n/aA change needs to go liveWebsite
Two separate deploy paths depending on what's being changed
From codeOrdinary WordPress/Elementor pages (like all the ones above) are edited and published directly on the live site via the WP REST API with an application-password login — there is no staging site (retired). The separate internal backend portal (
system.swingfitacademies.com, where the Game Plan Builder and check-in tools live) is a static-HTML+PHP mini-site on the same Hostinger account, deployed by SSH/SFTP (Python + paramiko) or, when SFTP credentials are stale, through the Hostinger hPanel File Manager in the browser.See it@references/deployment-process.md and @references/server-access.md for the exact commands/paths
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Where does the evaluation button actually send someone right now? | Click 'Book my evaluation' on /golf-swing-evaluation/ or /membership/ and watch where the browser lands | It should land on a live booking/checkout page with the right slot still selected, not a generic homepage |
| Where does a pricing-page pack button go? | /payg/, hover any package | Destination host is store.swingfitacademies.com |
| Where does the header 'Book' button go? | Any page, top-right button | Destination host is asia.golfmanager.com/swingfit |
| Is the tracking still firing? | Browser dev tools > Network, filter gtm/fbevents, reload any page | GTM container and Meta pixel requests fire on load |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Evaluation/membership CTA destination | Elementor edit on /golf-swing-evaluation/ and /membership/, the button widget's link field | changes where 'Book my evaluation' sends people |
| Homepage tracking tags | Google Tag Manager container GTM-N765MP89 | most page tags fire through here, not hardcoded per page |
Good to know
No staging site
All WordPress work happens directly on the live site since staging was retired; changes are previewed in the editor and verified live after publish, one change at a time.
Custom-template pages store copy differently
A few pages (join, confirmation, members, the low-ticket ad landing pages) use a custom PHP template pulling body copy from ACF postmeta rather than the normal Elementor JSON, so they need SSH access to edit, not just the REST API.
The backend portal is a separate mini-site
system.swingfitacademies.com (Game Plan Builder, check-in tools, coach/success-team hubs) is static HTML + PHP living alongside WordPress on the same server, kept from colliding with WordPress's rewrite rules by a root .htaccess exception.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (5)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
zbooking.us short linkFaNfO | other | Active | visitor click none | Redirects (301) to itself then (302) to a specific Zoho Bookings service slot URL on richard-swingfitacademies64.zohobookings.com, which itself 301s to the bare zohobookings.com root, dropping the slot id. | Elementor button widgets on /golf-swing-evaluation/ and /membership/n/a - third-party short link, no source |
sfaRoadmapCapture1446733000000766001 | function | Active last run 2026-08-27 (most | POST from the homepage 3-question roadmap quiz none (unconditional on submit) | Creates one Player_Roadmap record (Roadmap_ID prefix RM-) per submission and matches/creates the person as a Lead or Contact by email; args: fullName, email, goal, currentLevel, commitment, pageUrl. | Zoho CRM > standalone function, called via sfa-roadmap-capture.php on the Hostinger serverstate/workstreams/roadmap-tool/sfaRoadmapCapture.deluge.txt |
Google Tag Manager containerGTM-N765MP89 | other | Active | page load none | Fires GA4 and other page tags; a Meta Pixel fbq call and connect.facebook.net script are also present on every page load, independent of GTM. | loaded on every WordPress page (head + noscript iframe fallback) n/a - GTM container, managed in Tag Manager UI |
Contact page Web-to-Case form1043640000010401039 | form | Active | visitor submits the contact form none | Posts to desk.zoho.com/support/WebToCase, creating a Zoho Desk support ticket - not a CRM lead. | /contact/ page, Zoho Desk embedn/a - Zoho Desk hosted widget |
Backstage embeddable registration widgetn/a | other | Available | click on an element matching the widget's clickableElements selector one widget script load per page, then window.ZBSCheckOutWidget._createWidget called once per event | Opens the Backstage checkout for one specific event (eventUrl: https://events.swingfitacademies.com/embed/<slug>/buyTickets) in a themed modal overlay instead of a full navigation, when wired up. The live /member-events/ page uses plain links to the Backstage event page instead. | static.zohocdn.com/backstage/.../register-widget.min.js, available for use on event pagesstate/workstreams/member-events/zoho-backstage-embed-widget-reference.md |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Player_Roadmap | Roadmap_ID | unique id per submission, prefixed by source (RM- homepage quiz, MC- member check-in, GP- Game Plan Builder) | sfaRoadmapCapture / sfaevalcheckinsave / sfaGamePlanSave |
| Player_Roadmap | Source | where the record came from | sfaRoadmapCapture (Website) |
IDs and references
| What | Value |
|---|---|
| GTM container | GTM-N765MP89 |
| Backstage event URL pattern | events.swingfitacademies.com/embed/{eventKey}/buyTickets |
| Referral Factory campaign link | refer.swingfitacademies.com/cltASgmF |
| sfaRoadmapCapture function id | 1446733000000766001 |
All flows › Game Plan tools
The Game Plan Builder, roadmap tool and member check-in
Three related tools let a coach, Member Success, or a member self-rate a golf game and build a level-by-level plan, all writing into the same CRM history module.
- Starts when
- A coach, a Member Success staffer, or a member opens one of: the homepage roadmap quiz,
/coaches/game-plan.htmlor/success-team/game-plan.html(Game Plan Builder), a shared Game Plan link (system.swingfitacademies.com/plans/{id}/), or the public member check-in tool at/build-roadmap/. - Covers
- Covers three self-contained tools that share one CRM module (
Player_Roadmap): the homepage 3-question roadmap quiz, the interactive Game Plan Builder used live by coaches/Member Success (and by members via a shared link), and the member self-check-in tool at/build-roadmap/. Does not cover the paid evaluation booking/session flow itself (seeeval-booking-payment-to-mrr-funnel) or theMember_Planmodule a coach separately maintains as the durable source of truth. - Systems
- Website, Zoho CRM
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Visitor answers 3 questionsWebsite
Homepage roadmap quiz — the lightest-weight capture
Verified liveA 3-question quiz on the homepage (goal, current level, commitment) posts name/email/answers to
sfa-roadmap-capture.php, which calls CRM functionsfaRoadmapCapture. It matches or creates the person as a Lead/Contact and creates one append-onlyPlayer_Roadmaprecord (RM-id prefix,Source = Website). The quiz's on-page result scrolls to the pricing section rather than opening a full plan.See itPlayer_Roadmaprecords withRoadmap_IDstartingRM- - T+0Coach or Member Success opens the tool live with a playerWebsite
Game Plan Builder — the full interactive tool, used live in a conversation
From codeTwo versions of the same tool —
/coaches/game-plan.htmland/success-team/game-plan.html— run entirely client-side (no server call for the build itself). The user rates five game domains (Technique, Long game, Approach, Short game, On-course/Tracking) 1-5, sets a current stage and a goal stage, and the tool maps the stages between as a pathway with lesson estimates, a lessons-per-month throttle, and separate membership-vs-PAYG pricing for lessons and for practice. It renders a stage-climb visual, a radar chart and a printable/presentable plan, and auto-saves the in-progress build to the browser'slocalStorageso a refresh doesn't lose it.See itOpen either URL and build a plan; nothing is saved anywhere until 'Save & send' is clicked - T+~1-2sCoach/MS clicks 'Save & send to client'Website
Saving a Game Plan writes a local record, a shareable client page, and a CRM record
Verified livesave-game-plan.phpstores the full plan (JSON + a text summary) off the web root at/home/u245874645/plans_data/{id}/, keyed by a stable id derived from the client's name and email so re-saving the same client versions the same record (v1, v2, ...) instead of duplicating. It publishes a shareable link atsystem.swingfitacademies.com/plans/{id}/and, in the same request, calls CRM functionsfaGamePlanSaveto write aPlayer_Roadmaprecord (GP-id prefix) with the plan URL, version, current/goal level and a summary.- The shared link reopens the tool pre-filled, not a frozen snapshotFrom codeT+0 on link open
system.swingfitacademies.com/plans/{id}/is a small redirect page that sends the visitor into the live, interactive Game Plan Builder pre-loaded with their own ratings, level, goal and practice frequency via a URL parameter, so they can keep exploring outcomes themselves. It falls back to a static snapshot only if the encoded state is missing or would make the link too long.
See itPlayer_Roadmaprecords withRoadmap_IDstartingGP-; the record'sPlan_URLfield - T+0Member opens the self-check-in toolWebsite
Member check-in — a public, member-facing self-rating tool
Verified live/build-roadmap/(WordPress page embedding an iframe) loadsmember-checkin.htmlon the backend portal — a member-facing variant of the same self-rating tool (five domains, 1-5, all required), with a lessons-per-month and practice-commitment step, and no pricing shown. On submit it posts tosave-eval-checkin.php, which calls the shared CRM functionsfaevalcheckinsavewithsourceToolset so the backend can tell a member-checkin submission apart from an evaluation-intake or Member-Success-phone submission using the same function.See itPlayer_Roadmaprecords withRoadmap_IDstartingMC- - T+~1-2sMember submitsZoho CRM
sfaevalcheckinsave writes the record and guards against a repeat submission
From codeThe function matches or creates the person (Contact/Lead), writes one
Player_Roadmaprecord with theMC-prefix, and checks a 'one-per-member' guard (any existing Roadmap_ID already starting with the member's guard prefix blocks a second create) so a member can't spam duplicate check-ins. It also sends the member their own plan-recap email when the function's email step is not in test mode.See itA second submission from the same already-checked-in member returns analreadyCompletedresponse instead of creating a new record
Emails and messages
CustomerMember check-in plan recapVerified livethe member's own roadmap/plan summary
Full text (not found (would need a read of sfaevalcheckinsave_LIVE_2026-09-17.deluge's email section))
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did a member's check-in actually save? | Zoho CRM > Player_Roadmap, filter Roadmap_ID starts with MC- | a new record appears with the member's Current_Level, Goal_Level and a Summary |
| Did a coach's saved Game Plan reach the CRM? | Zoho CRM > Player_Roadmap, filter Roadmap_ID starts with GP-, or open the plan's shareable link and confirm Plan_URL matches | a GP- record with the same Plan_URL the coach was given to share |
| Is the homepage quiz still being used by real visitors? | Zoho CRM > Player_Roadmap, filter Roadmap_ID starts with RM-, sort by Created Time | recent, real-looking names/emails, not test data |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Homepage roadmap quiz | Remove/hide the quiz block on the homepage in Elementor | stops new RM- Player_Roadmap records; does not affect the Game Plan Builder or member check-in |
| Member check-in tool | Unpublish/redirect WordPress page hosting /build-roadmap/, or remove the iframe | stops new MC- records; the underlying member-checkin.html stays live on the backend portal unless also removed |
Good to know
One shared history module, one separate 'current truth' module
All three tools write to Player_Roadmap, an append-only history of what someone said at a point in time (never updated, never overwritten — a new submission is a new record). The separate Member_Plan module is the one living, coach-maintained record of a member's current level/goal that the portal actually uses day to day; a self-reported Roadmap entry never overwrites it.
Roadmap_ID prefix tells you the source at a glance
RM- = homepage quiz, GP- = Game Plan Builder save, MC- = member check-in — same module, three different front doors.
Pricing is hardcoded per tool, not pulled live
The Game Plan Builder's membership/PAYG/practice prices are written directly into its HTML file and must be manually kept in sync with the canonical pricing reference whenever prices change.
The Game Plan Builder needs no login and no server round-trip to build a plan
Building and previewing a plan is 100% client-side JavaScript; a server call only happens once, when 'Save & send' is clicked.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (5)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
sfaRoadmapCapture1446733000000766001 | function | Active last run 2026-08-27 (most | POST from the homepage 3-question quiz none | Creates one Player_Roadmap record (RM- prefix) and matches/creates the person as Lead or Contact. Args: fullName, email, goal, currentLevel, commitment, pageUrl. | CRM standalone function, called by public_html/sfa-roadmap-capture.phpstate/workstreams/roadmap-tool/sfaRoadmapCapture.deluge.txt |
save-game-plan.phpn/a | other | Active | POST from game-plan.html or game-plan-embed.html 'Save & send to client' none | Stores the plan JSON + text summary + client-facing HTML off web root at /home/u245874645/plans_data/{id}/v{n}.json, computes a stable id from name+sha1(email), publishes the shareable redirect page at /system/plans/{id}/, then synchronously calls sfaGamePlanSave and checks its JSON response's own ok field (not just HTTP 200) before reporting crmSynced. | system.swingfitacademies.com/system/save-game-plan.php domains/operations/backend-systems/deployed/system/save-game-plan.php |
sfaGamePlanSaveapi_name sfaroadmapsave (execute-URL slug); internal_name sfaGamePlanSave | function | Active last run 2026-09-23 (mult | called synchronously by save-game-plan.php on every Save & Send none | Upserts into Player_Roadmap keyed to versioning per client (GP- prefix), writing Plan_URL (short redirect link, capped by Zoho's 450-char field limit), Summary, Version, Current_Level/Goal_Level, matching an existing Contact/Lead by email or creating a Lead. Args: fullName, email, currentLevel, goal, recommendedRoute, planUrl, summaryText, version. | CRM standalone function domains/operations/backend-systems/sfaGamePlanSave.deluge.txt |
member-checkin.htmln/a | other | Active last run 2026-09-18 (most | member loads the page and submits all five domain ratings required | Client-side five-domain 1-5 self-rating + lessons/month + practice-commitment steps, no price shown; posts sourceTool:'member-checkin' plus ratings baked into the summary text to save-eval-checkin.php. | system.swingfitacademies.com/member-checkin.html, iframed on WordPress page 9076 (/build-roadmap/) domains/operations/backend-systems/deployed/system/member-checkin.html |
sfaevalcheckinsave1446733000000779001 | function | Active last run 2026-09-18 (most | POST from member-checkin.html, eval-checkin.html or roadmap-checkin.html (shared backend, branches on sourceTool) one-per-member guard: blocks a second create if a Roadmap_ID already exists with the member's guard prefix (MC- path) | Matches/creates the person, writes one Player_Roadmap record with the sourceTool-appropriate id prefix (MC- for member check-in), and sends the member their own recap email when EMAIL_TEST_MODE is off. Args: fullName, email, currentLevel, goal, commitment, route, worthIt, timeInDubai, evalType, summaryText, sourceTool, capturedBy. | CRM standalone function, called via save-eval-checkin.php state/workstreams/level-checkin-tool/sfaevalcheckinsave_LIVE_2026-09-17.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Player_Roadmap | Roadmap_ID | unique id, prefixed by source: RM- (homepage quiz), GP- (Game Plan Builder), MC- (member check-in) | sfaRoadmapCapture / sfaGamePlanSave / sfaevalcheckinsave |
| Player_Roadmap | Plan_URL | the shareable Game Plan link; capped at 450 characters by Zoho | sfaGamePlanSave |
| Player_Roadmap | Version | increments each time the same client's Game Plan is re-saved | sfaGamePlanSave |
| Player_Roadmap | Source | origin picklist; all three tools currently write 'Website' (a distinct 'Member Page' value was requested but not confirmed added) | sfaRoadmapCapture / sfaGamePlanSave / sfaevalcheckinsave |
| Player_Roadmap | Current_Level / Goal_Level | self-reported level and target, matched from each tool's own dropdown wording via fragment-matching in each function | sfaRoadmapCapture / sfaGamePlanSave / sfaevalcheckinsave |
IDs and references
| What | Value |
|---|---|
| sfaRoadmapCapture function id | 1446733000000766001 |
| sfaevalcheckinsave function id | 1446733000000779001 |
| Player_Roadmap module | CustomModule39, id 6296422000051896790 |
| localStorage keys (Game Plan Builder) | swingfit_gameplan_coach_v1 / swingfit_gameplan_ms_v1 |
All flows › New lead
When a new lead comes in (website form or Meta lead ad)
A new Lead is created in CRM from a website form or Meta ad, gets an owner, attribution fields, and possible staff/customer notifications.
- Starts when
- A record is created in the Zoho CRM Leads module — from a swingfitacademies.com form/tool, from Meta's native Lead Ads sync, or entered manually by staff.
- Covers
- Covers a Lead record's first minute in Zoho CRM: how it's created (website tools vs. Meta lead ads), who it's assigned to, what UTM/attribution gets captured, and what emails/WhatsApp/Cliq pings are supposed to fire. Stops at the point a lead books and pays for an evaluation and converts to a Contact — see the eval-booking trace for that handoff. Does not re-audit UTM field design (UTM Standard v1.1 governs that).
- Systems
- Website (Zoho Forms / Elementor / custom PHP endpoints), Zoho CRM, Zoho Flow, Meta (native Lead Ads sync + Conversions API), Zoho Cliq, WhatsApp (via CRM extension)
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Lead createdWebsite
Website visitor submits a form or tool
From codeswingfitacademies.com carries several separate lead-capture surfaces, each with its own backend function, all landing in the same CRM Leads module: Zoho Forms/Elementor forms embedded on pages; the homepage roadmap tool (
sfaroadmapcapture, REST API endpoint called bysfa-roadmap-capture.php); the Game Plan Builder embed (sfagameplansave, called bysave-game-plan.php); native website popups (sfaPopLeadCapture, upserts a Lead with email + which of 6 popup variants it came from); and a Break 100 / commitment-style quiz whose answers land directly on Lead fieldsBreak_LevelandScore_Goal. Each matches by email against existing Contact/Lead first; if no match, it creates a new Lead.- Real exampleVerified liveT+0
Lead 6296422000053510054 (created 2026-09-18) carries Break_Level="Break 100" and Score_Goal="I'm brand new" — confirms the Break 100 quiz/roadmap-style tool as the real source, even though Lead_Source itself was left blank on this record.
See itCRM Leads list, sort by Created Time; open a record and check Break_Level/Score_Goal (roadmap/quiz tools) or Landing_Page/First_Visited_URL (form tools) for which surface it came from. - T+0Lead createdZoho CRM
Meta lead ad visitor is synced in
Verified liveA lead submitted through a native Facebook/Instagram Lead Ads form is created directly in CRM by Zoho's built-in Meta ads-lead sync (not a Zoho Flow), stamping Lead_Source = "Meta_Ads". The picklist still carries two older values ("Social - Facebook", "Social - Instagram") from an earlier setup that current traffic no longer uses. Separately, an outbound-only flow (
crm_to_meta, workflow rule "Leads_ZohoFlow_ZCRM - Meta") fires a webhook back out to Zoho Flow on every Lead create/edit — that pushes lead events to Meta's Conversions API so Meta can optimize ad delivery; it is not part of intake and does not create or touch Lead data.- Real exampleVerified live2026-08-23T09:42+04:00
Lead 6296422000051579034 (created 2026-08-23T09:42+04:00): Lead_Source="Meta_Ads", Owner correctly set to Member Success @ SFA. UTM_Source on this record is blank - native in-app lead ad forms don't carry a website UTM.
- crm_to_meta flow can't be opened for inspectionFrom coden/a
The archive's Flow-configuration capture could not open
crm_to_meta("ZCRM - Meta") for a full read, so its exact node logic isn't documented here - only its on/off state and last-fired time are visible from the CRM workflow-rule side.
See itLead record's Lead_Source field = "Meta_Ads"; CRM Automation > Workflow Rules > Leads > "Leads_ZohoFlow_ZCRM - Meta" (last-executed timestamp) for the outbound side. - T+0same transactionZoho CRM
Lead is assigned to Member Success
Verified liveTwo active rules push every new Lead toward one shared CRM user, "Member Success @ SFA":
Lead Owner - Member Successassigns that user on every create, andAssign Lead Ownerruns right behind it as a backstop, reassigning if the Owner is anything else. Both target the same user record and both fire on create.See itLead record's Owner field. - T+0same transactionZoho CRM
Client Status / Lifecycle Status are stamped
Verified liveAutomate Client Statusruns two field-update actions on create — "Client Status Update" and "Update Lifecycle Status" — writing the Lead's starting Client_Status and Lifecycle_Status (seen live as "Lead" for both).See itLead record's Client_Status and Lifecycle_Status fields. - T+0same transactionZoho CRM
De-duplication check runs — and can delete the new lead
From codeDe-Duplicate the Leads created via LeadChainfires the custom functionDe_duplicate_leadson every Lead create, unconditionally. If the new lead has a Phone but no Mobile, it searches for any other Lead with the exact same Full_Name; if it finds one whose Mobile equals the new lead's Phone, it calls the CRM API to DELETE the brand-new lead outright — no merge, no soft-delete, no email cross-check.See itn/a from the UI — only visible as a Lead that never appears (deleted moments after creation). CRM Setup > Automation > Workflow Rules > Leads > "De-Duplicate the Leads created via LeadChain" for the rule; function source for the logic. - T+0same transactionZoho CRM
UTM / attribution fields land on the Lead
From codeLead_Source, Lead_Channel, UTM_Source/Medium/Campaign/Term/Content, Google_GCLID, FBCLID, msclkid, GA_Client_ID, Landing_Page and First_Visited_URL/Time are all captured on the Lead record per UTM Standard v1.1 (not re-audited here). Four picklist rules (
Set Lead Channel – Google Ads/Facebook/Instagram/Google Organic) andMap Campaign – Instagram Juniorare meant to translate the raw UTM values into the normalized Lead_Channel field for reporting.See itLead record's UTM_* fields and Lead_Channel. - T+0designed, currently offZoho CRM
Staff are notified of the new lead
UnverifiedThree rules are designed to tell Member Success a lead just came in: an internal email (
NEW LEAD - Email, action "Admin Alert", skips Walk-in/Website-Chat sources), a WhatsApp ping to the Main Reception SFA number (New Lead WA Notify, template "lead_just_in", via a third-party WhatsApp-for-CRM extension), and a Cliq post to the #New Lead Notification channel with the lead's email/name/phone (Jan 2026 New Lead Notification).See itCRM Setup > Automation > Workflow Rules > Leads, filter by name for "NEW LEAD", "New Lead WA Notify", "Jan 2026 New Lead Notification". - T+0, instant, designeddesigned, currently offZoho CRM
Lead gets an instant reply email
UnverifiedsfaSpeedleadAutoReply Triggeris designed to firesfaSpeedleadAutoReplyon every Lead create, sending the lead an immediate first-touch email, with the template chosen by which capture surface set Pop_Source (eval / intro / join / referral / value-report, defaulting to the Eval template).See itCRM Setup > Automation > Workflow Rules > Leads > "sfaSpeedleadAutoReply Trigger". - T+1h (scheduled), designeddesigned, currently offZoho CRM
Paid-lead abandon-recovery nudge
Verified liveFor leads with Lead_Source Meta_Ads or Google_Ads,
Lead Abandon Recovery - Evalis designed to schedule an email ("Booking Abandon Eval") plus a WhatsApp template ("booking_abandon") one hour after the lead is created or edited, nudging them to book their evaluation.- Real exampleVerified liveT+59m
Lead 6296422000051579034 (Meta_Ads, created 2026-08-23T09:42:40+04:00) received an email "Your Swing Evaluation session is waiting." from info@swingfitacademies.com at 2026-08-23T10:42:05+04:00 - T+59 minutes, matching this rule's 1-hour scheduled action.
See itCRM Setup > Automation > Workflow Rules > Leads > "Lead Abandon Recovery — Eval"; lead's Emails related list. - next day 09:00overnight leadsZoho Cliq
Overnight leads are listed for a 9am call
From codeLeads that arrive between 10pm and 9am are not called before 9am unless they asked for it. At 09:00 every day LeadBot posts in the Member Success team channel with every lead from that window that hasn't been contacted yet: name, phone, source, arrival time and a CRM link. Staff call or WhatsApp them and update Lead Status. Each listed lead gets the CRM tag "Overnight Lead". If there were no overnight leads, nothing is posted.
See itMember Success team channel in Cliq at 9am; CRM Leads filtered by tag "Overnight Lead". - ongoingfirst contact trackingZoho CRM
First-response time is tracked
Verified liveLead First Contactstamps a timestamp the first time Member Success changes Lead_Status away from empty;First Response Time Rulestamps a related timestamp off Evaluation_Status changes.See itLead record's Lead_Status / Evaluation_Status change history. - when the lead books & pays for an evaluationconversionZoho CRM
Lead converts to Contact
UnverifiedOnce the lead books and pays for their evaluation, the Lead record converts to a Contact and the booking flow takes over. Full detail is out of scope here — see the eval-booking trace.
See itSee references/systems-handbook/traces/eval-booking.json.
Emails and messages
TeamAdmin Alert (NEW LEAD - Email)Unverifiednot pulled — embedded in the workflow rule's email-notification action, not a template-gallery record
Full text (not found)
CustomerBooking Abandon EvalVerified liveYour Swing Evaluation session is waiting.
Full text (not found (template record not opened this pass))
CustomersfaSpeedleadAutoReply instant replyUnverifiednot pulled — one of 5 templates by Pop_Source (Eval/Intro/Join/Referral/Value Report)
Full text (crm_deluge_source/sfaspeedleadautoreply.deluge - confirms all 5 IDs are unresolved placeholders)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| How do I know a new lead just came in? | CRM Leads list view, sorted by Created Time descending (or filtered to Owner = Member Success @ SFA) | The lead appears within seconds of submission with Owner already set and Client_Status = "Lead". |
| Why is this lead's Lead_Channel blank? | Lead record's UTM_Source / UTM_Medium fields | Lead_Channel populated whenever UTM_Source contains google/facebook/instagram (and, for Google, UTM_Medium contains cpc). |
| Did this lead get any email or WhatsApp from us? | Lead record > Related List > Emails; Tasks related list for follow-up tasks | An email, WhatsApp message, or task on this list matching a notification/nurture rule that is currently active. |
| Who owns a brand-new lead? | Lead record's Owner field | Should read "Member Success @ SFA" (the shared pool user), never a named coach, unless deliberately reassigned later. |
| Which leads came in overnight and still need a call? | LeadBot's 9am post in the Member Success team channel, or CRM Leads filtered by tag "Overnight Lead" | Every lead created 10pm-9am that is still New Lead or has no status appears in that morning's post. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| NEW LEAD - Email (staff email alert) | CRM Setup > Automation > Workflow Rules > Leads > "ZZOFF-2026-09 NEW LEAD - Email" (inactive since 2026-09-09) | Internal email telling Member Success a lead arrived. |
| New Lead WA Notify (staff WhatsApp ping) | same location, "ZZOFF-2026-09 New Lead WA Notify" | WhatsApp ping to the Main Reception SFA number. |
| Jan 2026 New Lead Notification (staff Cliq post) | same location, "ZZOFF-2026-09 Jan 2026 New Lead Notification" | Cliq message to #New Lead Notification with the lead's email/name/phone. |
| sfaSpeedleadAutoReply Trigger (instant customer reply) | same location, "ZZOFF-2026-09 sfaSpeedleadAutoReply Trigger" | Immediate first-touch email to the lead themselves. |
| Lead Abandon Recovery — Eval (paid-lead nudge) | same location, "ZZOFF-2026-09 Lead Abandon Recovery — Eval" | 1-hour-later email + WhatsApp nudge to Meta/Google Ads leads who haven't booked yet. |
| 6 more lead-side WA/email rules (WA Message Sent, Send WA 1, Send WA Intro, Referral Confirmation, Send WA 1 LGE, Send WA 1 Membership) | same location, all renamed with the "ZZOFF-2026-09" prefix | Various follow-up WhatsApp/email sends further down the lead's contact journey (11 lead-side rules total switched off 2026-09-09). |
| Overnight leads 9am post | CRM Setup > Automation > Schedules > "sfaOvernightLeadsCall Schedule" (status toggle) | The daily 9am LeadBot list of overnight leads in the Member Success channel, and the Overnight Lead tag. |
Good to know
Lead ownership is one shared user
"Member Success @ SFA" is a single shared CRM user, not a round-robin of individual reps. Two separate rules (create-time assign, and an override backstop) both push toward this same target, which is why ownership rarely drifts on standard leads.
Lead_Source picklist carries old and new values side by side
The Lead_Source picklist still lists "Social - Facebook" and "Social - Instagram" from an earlier setup, but the current native Meta Lead Ads sync writes "Meta_Ads" instead — useful context when reading older vs. newer leads.
Website intake is several tools, one module
Zoho Forms/Elementor embedded forms, the homepage roadmap tool, the Game Plan Builder embed, native website popups, and a Break 100 commitment-style quiz all feed the same Leads module through separate backend functions — there isn't one single "website form".
The Meta-facing flow is one-way, outbound
crm_to_meta ("ZCRM - Meta") sends CRM lead events to Meta's Conversions API for ad optimization; it does not create leads. Lead intake from Meta ads is a native Zoho CRM integration, not a Zoho Flow.
UTM/attribution capture
Lead_Source, Lead_Channel, UTM_Source/Medium/Campaign/Term/Content, Google_GCLID, FBCLID, msclkid, GA_Client_ID, Landing_Page and First_Visited_URL/Time are all captured on the Lead per UTM Standard v1.1 — see that standard for the full spec, not re-audited here.
Inbound WhatsApp from a prospect is a separate system
If a prospect messages the business WhatsApp number directly rather than filling a form, that's routed through the separate "WA-2" inbound-WhatsApp Cliq-notification system, not through the Lead-create rules described here.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (28)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
sfaroadmapcapture1446733000000766001 | function | Active | POST from sfa-roadmap-capture.php on the website n/a (standalone endpoint) | Upserts a Lead by email; if none found, creates one, writing Break_Level and Score_Goal from the roadmap/quiz answers. | Website homepage roadmap tool -> CRM REST API endpoint crm_deluge_source (standalone; 7,502 chars) |
sfaPopLeadCapture1446733000000693004 | function | Active | popup submit on the website n/a (standalone endpoint) | Upserts a Lead by email, stamping which of 6 popup variants it came from (Pop_Source). | Website popups -> CRM REST API endpoint crm_deluge_source (standalone; 1,007 chars) |
sfagameplansave | function | Unknown | POST from save-game-plan.php on the website n/a | Upserts a Lead/Contact from the Game Plan Builder tool's inputs. | Website Game Plan Builder embed -> CRM REST API endpoint not found in $HOME/arch this session |
Native Meta Lead Ads sync | other | Active | Facebook/Instagram Lead Ads form submit n/a | Creates the Lead directly in CRM, stamping Lead_Source = "Meta_Ads". No UTM_Source is carried since there's no website click. | Zoho CRM Setup > Marketplace/Channels > Facebook/Instagram Lead Ads (native integration, not a Flow) n/a - native Zoho integration, no Deluge source |
Leads_ZohoFlow_ZCRM - Meta6296422000042060001 | workflow rule | Active last run 2026-10-11T08:46 | Lead create/edit none (unconditional) | Fires an outbound webhook (action type "webhooks") to Zoho Flow's crm_to_meta ("ZCRM - Meta") flow, which pushes lead events to the Meta Conversions API for ad optimization. Does not create or modify Lead data - outbound only. | CRM Setup > Automation > Workflow Rules > Leads n/a for the rule; the downstream flow `crm_to_meta` returns a formatting error/404 in the archive capture, so its node graph is unreadable |
Lead Owner - Member Success6296422000002834057 | workflow rule | Active last run 2026-10-10T21:09 | Lead create none (unconditional) | Assigns Owner to the shared user "Member Success @ SFA" (assign_owner action). | CRM Setup > Automation > Workflow Rules > Leads |
Assign Lead Owner6296422000016357005 | workflow rule | Active last run no execution rec | Lead create Owner not_equal "Member Success @ SFA" | Backstop re-assignment to "Member Success @ SFA" if the create-time rule above didn't stick. | CRM Setup > Automation > Workflow Rules > Leads |
Automate Client Status6296422000013417034 | workflow rule | Active last run 2026-10-10T21:09 | Lead create none (unconditional) | Two field-update actions: "Client Status Update" and "Update Lifecycle Status", both stamping starting values (seen live as "Lead"). | CRM Setup > Automation > Workflow Rules > Leads |
De-Duplicate the Leads created via LeadChain6296422000006502051 | workflow rule | Active last run 2026-10-10T21:09 | Lead create none (unconditional) - matching logic is inside the function | Runs function De_duplicate_leads. | CRM Setup > Automation > Workflow Rules > Leads |
De_duplicate_leads1446733000000092001 | function | Active last run 2026-09-22T02:26 | called by workflow rule of the same purpose n/a | If the new Lead has a Full_Name and a Phone but no Mobile, searches other Leads with the exact same Full_Name; for any match whose Mobile equals the new lead's Phone, DELETEs the brand-new lead via the CRM v7 REST API (crm_oauth_connection) - unconditional hard delete, no merge, no email cross-check, no log of the deleted fields. | CRM Setup > Automation > Functions crm_deluge_source/de_duplicate_leads.deluge (1,219 chars, full body read) |
Set Lead Channel – Google Ads6296422000032987765 | workflow rule | Active last run 2026-10-08T07:31 | Lead create/edit UTM_Source contains "google" AND UTM_Medium contains "cpc" | Field-update "Set Lead Channel – Google Ads" writes the normalized Lead_Channel value. Structurally can never match current Google Ads traffic, which stamps UTM_Medium="pmax" (Performance Max), not "cpc". | CRM Setup > Automation > Workflow Rules > Leads |
Set Lead Channel – Facebook6296422000032987744 | workflow rule | Active last run never | Lead create/edit UTM_Source contains "facebook" | Field-update "Set Lead Channel – Facebook". Native Meta Lead Ads leads carry no UTM_Source, so this rule's condition is not met. | CRM Setup > Automation > Workflow Rules > Leads |
Set Lead Channel – Instagram6296422000032987723 | workflow rule | Active last run never | Lead create UTM_Source contains "instagram" | Field-update "Set Lead Channel – Instagram". Same never-fired gap as the Facebook rule. | CRM Setup > Automation > Workflow Rules > Leads |
Set Lead Channel – Google Organic6296422000032987786 | workflow rule | Active | Lead create/edit UTM_Source contains "google" AND UTM_Medium contains "organic" | Field-update "Set Lead Channel – Google Organic". | CRM Setup > Automation > Workflow Rules > Leads |
Map Campaign – Instagram Junior6296422000032987807 | workflow rule | Active | Lead create/edit UTM_Campaign contains "ig_junior" | Field-update "Campaign Name" - normalizes the campaign label for this specific Instagram junior-golf campaign. | CRM Setup > Automation > Workflow Rules > Leads |
NEW LEAD - Email6296422000001597020 | workflow rule | Inactive last run 2026-09-08T13:26 | Lead create Lead_Source not_equal ["Walk in","Website Chat"] | Email notification action "Admin Alert" tells Member Success a lead arrived. | CRM Setup > Automation > Workflow Rules > Leads (currently named "ZZOFF-2026-09 NEW LEAD - Email") |
New Lead WA Notify6296422000006965001 | workflow rule | Inactive last run 2026-09-08T13:26 | Lead create/edit Lead_Source not_equal empty | Sends a WhatsApp message (template "lead_just_in", template id 67ea4eac31328bd8985441dc) to the Main Reception SFA number via the third-party "WhatsApp messaging for Zoho CRM" extension. | CRM Setup > Automation > Workflow Rules > Leads (currently "ZZOFF-2026-09 New Lead WA Notify") |
Jan 2026 New Lead Notification6296422000029070009 | workflow rule | Inactive last run 2026-09-08T13:26 | Lead create Lead_Status equal "New Lead" | Posts to Cliq channel #New Lead Notification: "New Lead has been Created / Email: Email / Last Name: Last_Name / Phone Number: Phone". | CRM Setup > Automation > Workflow Rules > Leads (currently "ZZOFF-2026-09 Jan 2026 New Lead Notification") |
sfaSpeedleadAutoReply Trigger6296422000047217140 | workflow rule | Inactive last run 2026-09-08T13:26 | Lead create none (unconditional) | Runs function sfaSpeedleadAutoReply. | CRM Setup > Automation > Workflow Rules > Leads (currently "ZZOFF-2026-09 sfaSpeedleadAutoReply Trigger") |
sfaSpeedleadAutoReply1446733000000685003 | function | Inactive | called by workflow rule sfaSpeedleadAutoReply Trigger n/a | Reads Pop_Source to pick one of 5 hardcoded template-id variables (PASTE_TEMPLATE_ID_EVAL/INTRO/JOIN/REFERRAL/VALUE_REPORT); as of this capture all 5 are still literal unfilled placeholder strings, so the function's own guard aborts every run before sending (if(tid.contains("PASTE_TEMPLATE_ID")) return;). The send_mail call it would make also has no "org_email":true key. testMode is hardcoded "false" with a goLive="2026-07-16" date-guard already past. | CRM Setup > Automation > Functions crm_functions_live/functions/sfaSpeedleadAutoReply.deluge |
Lead Abandon Recovery — Eval6296422000045328189 | workflow rule | Inactive last run 2026-09-07T08:28 | Lead create/edit Lead_Source equal ["Meta_Ads","Google_Ads"] | Scheduled action +1 hour: email notification "Booking Abandon Eval" and a WhatsApp template "booking_abandon". | CRM Setup > Automation > Workflow Rules > Leads (currently "ZZOFF-2026-09 Lead Abandon Recovery — Eval") |
Lead First Contact6296422000006128063 | workflow rule | Active last run 2026-10-11T08:46 | field_update (Lead_Status changes away from empty) none beyond the field_update trigger | Field-update "First Action Update" stamps a first-response timestamp. | CRM Setup > Automation > Workflow Rules > Leads |
First Response Time Rule6296422000006128042 | workflow rule | Active last run 2026-08-20T11:02 | field_update (Evaluation_Status changes) none beyond the field_update trigger | Field-update "Book Timing Update" stamps a related response-time timestamp. | CRM Setup > Automation > Workflow Rules > Leads |
sfaOvernightLeadsCall Schedule6296422000047217146 | schedule | Active last run 2026-09-30T09:00 | Daily 09:00 Asia/Dubai (from 2026-09-26) n/a | Runs function sfaOvernightLeadsCall. This schedule slot previously ran sfaSpeedleadSLASweep (retired; function still exists, unattached) and was reused because the org is at the 50-schedule cap. | CRM Setup > Automation > Schedules n/a (schedule) |
sfaOvernightLeadsCallsfaovernightleadscall (API name) | function | Active last run 2026-09-30T09:00 | sfaOvernightLeadsCall Schedule Leads created 22:00 the previous day to 08:59 today (Dubai) whose Lead_Status is empty, New Lead or Connected via SalesIQ. Converted leads are excluded automatically. | If any match: LeadBot (Cliq bot 'leadbot') posts one message in #teammembersuccess listing name, phone, source, arrival time and CRM link, asking staff to call or WhatsApp from 9am and update Lead Status; tags each lead 'Overnight Lead'. No match: no post. Sends nothing to customers. | CRM Setup > Developer Hub > Functions (category: schedule) crm_email_templates/flows_bookings/sfaOvernightLeads_DRAFT_2026-09-23.deluge |
New Lead469029000000015001 | flow | Inactive/disabled | n/a - disabled n/a | Disabled flow (CRM -> Zoho SalesIQ), is_disabled=true, not referenced by any active automation. | Zoho Flow > folder "default" n/a |
Tag Leads469029000000011061 | flow | Inactive/disabled | n/a - disabled n/a | Disabled flow (CRM -> CRM tagging experiment); flow_status shows an error state, is_disabled=true. | Zoho Flow > folder "default" n/a |
Leads to ZMA469029000000011001 | flow | Inactive/disabled | n/a - disabled n/a | Disabled flow (CRM -> Zoho Marketing Automation), is_disabled=true. | Zoho Flow > folder "default" n/a |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Leads | Lead_Source | Where the lead came from (Meta_Ads, Google_Ads, Walk in, Website Chat, legacy Social - Facebook/Instagram, etc.) | native Meta Lead Ads sync; capture-surface functions; manual staff entry |
| Leads | Lead_Channel | Normalized channel for reporting (Google Ads / Facebook / Instagram / Google Organic) | Set Lead Channel – * field-update rules (see fix_additions for current mismatches against live UTM values) |
| Leads | UTM_Source / UTM_Medium / UTM_Campaign / UTM_Term / UTM_Content, Google_GCLID, FBCLID, msclkid, GA_Client_ID, Landing_Page, First_Visited_URL/Time | Attribution capture per UTM Standard v1.1 | website capture surfaces / native ad integrations |
| Leads | Break_Level / Score_Goal | Answers from the Break 100 quiz / roadmap tool | sfaroadmapcapture |
| Leads | Pop_Source | Which of 6 popup variants (or EVAL/INTRO/JOIN/REFERRAL/VALUE_REPORT/ORGANIC) captured the lead - drives which sfaSpeedleadAutoReply template would be chosen | sfaPopLeadCapture |
| Leads | Client_Status / Lifecycle_Status | Starting pipeline status, both stamped "Lead" on create | Automate Client Status |
| Leads | Owner | Should read the shared "Member Success @ SFA" user on every new lead | Lead Owner - Member Success / Assign Lead Owner backstop |
| Leads | Speedlead_Sent | Guards sfaSpeedleadAutoReply from re-sending; also read by the SLA sweep | sfaSpeedleadAutoReply |
IDs and references
| What | Value |
|---|---|
| Shared Lead-owner CRM user | Member Success @ SFA (id 6296422000002537001) |
| WhatsApp template - new-lead ping | lead_just_in (template id 67ea4eac31328bd8985441dc, channel 67aafecd89a67f744f6595ac) |
| Cliq channel - new lead | #New Lead Notification (id O5766196000001162001) |
| Cliq bot - overnight leads post | LeadBot (unique name leadbot, Organization scope) |
| Cliq channel - overnight leads post | #teammembersuccess (chat id CT_2243186866118877818_866431816) |
| CRM tag - overnight lead | Overnight Lead |
All flows › Evaluation booked
When someone books and pays for an evaluation
A customer books and pays for an evaluation online, which creates the GolfManager booking, CRM link, lesson credit, and coach briefing automatically.
- Starts when
- Customer picks a coach + time slot for a Golf Swing Evaluation or Intro to Golf Evaluation on the website and pays AED 99 through the embedded Zoho Checkout page.
- Covers
- Covers the paid first-session flow ("Golf Swing - Evaluation" / "Intro to Golf - Evaluation", ~AED 99) from the website payment through GolfManager booking creation, CRM linkage, credits, coach briefing and pre-session intake emails. Does not cover the eval itself, the outcome/debrief form content, or membership conversion after the eval (pointer only).
- Systems
- Website, Zoho Checkout, Zoho Flow, Zoho CRM, GolfManager, Zoho Books, Zoho Cliq, Meta Conversions API
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Slot picked, payment page loadsWebsite
Customer fills the Zoho Checkout page and pays
From codeThe evaluation is sold as a Zoho Checkout product with the slot/coach details carried as line-item/custom fields. Checkout is the actual booking surface for this flow, not Zoho Bookings and not GolfManager directly — GolfManager only sees a booking after payment succeeds.
See itZoho Checkout order in Zoho Checkout admin; matching Zoho Books invoice (SFA/xxxx/xxxxx, sales_channeldirect_sales, reference blank until the GM booking is created) - T+~1sOrder createdZoho Flow
Zoho's native "Zoho Checkout - Zoho CRM" flow creates the Contact + a Pending Evaluation_Booking
From codeThis is a built-in (no custom function) Zoho Flow — upserts the Contact and creates an
Evaluation_Bookingrecord with Status=Pending, the chosen resource/coach, Start/End time and Price, moments before or during the payment step. Because it uses only native connector actions we can't read its source, only its effect.- Pre-session intake invite fires here tooUnverifiedT+~1s
The workflow rule
evaluationbookingconfirmfires on this Evaluation_Booking CREATE and sends the pre-session intake invite email — see the Emails section for delivery status.
See itEvaluation_Booking record Created_Time vs. the linked Contact's Created_Time (near-identical in every example checked) - T+~1-2minPayment confirmedZoho Flow
Checkout payment success creates the real GolfManager booking, credit and Cliq alert
Verified liveFlow
Zoho Checkout to ZCRM/GM - GolfSwing Evaluation(Intro to Golf usesZCheckout to ZCRM/GM - Intro to Golf) calls functionZCRM_UpdatePaymentStatus_GMBookingCreation(CRM_UpdatePayStatus_GMBookingCreationfor Intro to Golf — a near-duplicate, same logic, different hardcoded product string). It finds the Contact by email, finds their Pending Evaluation_Booking, sets Status=Confirmed, finds-or-creates the customer in GolfManager, POSTs the real appointment to/api/model/bookingusing the resource/time/price already on the CRM record, then recharges a GM voucher for the eval and pays it via/api/billing/paySalesso GolfManager shows it fully settled. It also reads the paid Books invoice's line items and creates matchingCreditsrecords in CRM for any package top-ups on the same order, then posts a "New Booking" alert to Cliq.- Payment-failure branchFrom codeon payment failure
If the Checkout payment itself fails, flow
PaymentFailed - GolfSwing Evaluation/PaymentFailed - Intro to GolfcallsZcliq_PaymentFailed_Golf_Swing_Evaluation/ZcliqMsg_PaymentFailed_intro_to_golf_, which post a "Payment Failed" Cliq alert to the team channel.
See itGolfManager booking screen (search by customer); Zoho Books invoice status=paid; Contact's Credits related list; Cliq #New Bookings channel - T+~1-3minGM booking syncs backZoho CRM
The new GolfManager booking mirrors into CRM's Bookings module, which links back to the same Evaluation_Booking
Verified liveA separate GM->CRM sync flow (not custom-function based, not traced in this pass) writes a record into CRM's generic
Bookingsmodule. Its CREATE, where Resource_Name/Booking_Details contains "Evaluation", fires workflow rulesfaevalspinelink, which runs functionsfaEvalSpineLink. It matches back to the same Evaluation_Booking (by GM booking id, or by same player + same calendar day if not yet stamped), stamps GM_Booking_Id and Source=GolfManager onto it, finds-or-creates a Sales Pipeline Deal at stage "Evaluation/Intro Booked & Paid", and carries forward any earlier self-reported Player_Roadmap answers onto the booking. If no invite has been sent yet on this or a duplicate record for the same player/day, it also sends the pre-session intake email itself as a second path to the same result.See itEvaluation_Booking's GM_Booking_Id field; linked Deal in Sales Pipeline at "Evaluation/Intro Booked & Paid" - T+ (same create/edit)Coach owner stampedZoho CRM
Evaluation_Booking Owner is set to the matching coach
Verified liveRule
coachevaluationsweepfires on every Evaluation_Booking create/edit and functionsfaEvalCoachOwnerStamp1matches the booking's resource string against 6 named coaches to set record Owner.See itEvaluation_Booking record Owner field - T+ (same create)Ad attribution (conditional)Zoho Flow
Meta ad conversion logged, if this booking came from a Meta ad
From codeFlow
EvaluationBookingZCRM - Metafires on Evaluation_Booking create; if the record's UTM_Source ismeta_ads, functionEvaluationBookingZCRM_Metasends a hashed-email/phone "schedule" event (value AED 99) to the Meta Conversions API.See itMeta Events Manager, pixel 4473134646297796, event_source_url swingfitacademies.com/booking - variant, no payment stepReferral variant (pointer)Zoho CRM
A referred (comp'd) evaluation skips Checkout entirely
Verified liveWhen Status=Referral, rule
ReferralEvaluationBookingcalls functionReferralEvaluationBookingand creates the GolfManager booking directly — no Zoho Checkout charge, no Books invoice, no Credits record. This is the designed path for a comp'd evaluation via an existing member.See itEvaluation_Booking Status=Referral, no linked Books invoice - daily 10:00 (day before)Coach briefingZoho Cliq
Coach gets a pre-session briefing the day before
Verified liveRule
Coach Pre-Session Briefing Sweepfires once, the day before Start_Date_and_Time at 10:00, calling functionsfaevalbriefingsendtest(its internal name includes "test" though it is the live production version). It posts a "BEFORE YOU WALK IN" message to the assigned coach's Cliq DM with the player's intake answers (if completed) and a link to the Game Plan Builder tool.See itCoach's own Cliq DM the morning before the session - periodic (~hourly), gated by hours-to-sessionIntake backstopZoho CRM
A scheduled sweep catches bookings still missing their intake answers
Verified liveScheduled function
sfaEvalIntakeBackstopscans open-intake Evaluation_Booking records; well before the session it sends a catch-up copy of the intake invite, and closer to the session a shorter "Still time" nudge, to whichever bookings haven't completed intake yet.See itEvaluation_Booking's Intake_Nudge_Sent field; contact's Emails related list - T+0 after End_Date_and_TimeAfter the eval (pointer only)Zoho Cliq
Coach gets prompted for the outcome/debrief
Verified liveRule
Coach Post-Session Debrief Sendfires at the booking's End_Date_and_Time and callssfaEvalDebriefSend, sending the coach a prefilled debrief-form link via Cliq DM. What happens with that form (outcome logging, conversion) is out of scope for this page.See itCoach's Cliq DM after session end
Emails and messages
CustomerPre-session intake inviteUnverifiedTwo minutes now makes the hour better
Full text (crm_deluge_source/evaluationbookingconfirm.deluge (line 332) and crm_deluge_source/sfaevalspinelink.deluge (same template duplicated))
CustomerIntake backstop catch-up / nudgeUnverified"Two minutes now makes the hour better" (catch-up) or "Still time — two quick minutes before your evaluation" (nudge)
TeamCoach pre-session briefingVerified liven/a (Cliq message, not email)
Full text (crm_deluge_source/sfaevalbriefingsendtest.deluge (line 170, 291))
TeamNew Booking alertVerified liven/a (Cliq message to #New Bookings)
TeamPayment Failed alertUnverifiedn/a (Cliq message to #New Bookings)
TeamInternal "EMAIL SEND FAILED" noticesVerified live"<function name> EMAIL SEND FAILED" (variants: "(catchup)", "(nudge)")
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did this customer actually get their pre-session intake email? | Contacts > [contact] > Emails related list | An entry with subject "Two minutes now makes the hour better" and their own address as recipient — a blank list plus a checked Evaluation_Booking_Intake_Invite_Sent box only proves the send was attempted, not delivered |
| Did the eval booking make it into GolfManager and get paid? | GolfManager booking search by customer, or Zoho Books invoice for the AED 99 line | GolfManager booking status shows the sale as paid; Books invoice status = paid |
| Did the coach get their pre-session briefing? | Coach's own Cliq DM the morning before the session | A "BEFORE YOU WALK IN" message with the right date/time and Game Plan Builder link |
| Was a credit/voucher created for this eval? | Contact's Credits related list | A record named for the product (e.g. "GolfSwing Evaluation") with Balance 1 |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Pre-session intake invite (App/manual-create path) | CRM Settings > Automation > Workflow Rules > Evaluation_Booking > evaluationbookingconfirm | The invite attempt on manually/app-created bookings only |
| Whole GM->CRM linkage for evals (record link, invite, Deal, roadmap carry-forward) | Workflow Rules > Bookings > sfaevalspinelink | All of that — this rule is not just the email, turning it off breaks eval-to-CRM tracking entirely |
| Coach pre-session briefing | Workflow Rules > Evaluation_Booking > Coach Pre-Session Briefing Sweep | The day-before Cliq DM to the coach only |
| Payment -> real GolfManager booking + credit + Cliq alerts | Zoho Flow > "Zoho Checkout - Zoho CRM" folder > "Zoho Checkout to ZCRM/GM - GolfSwing Evaluation" / "ZCheckout to ZCRM/GM - Intro to Golf" | The entire pay-to-real-booking chain — paid customers would stop getting an actual GolfManager appointment |
Good to know
Two products, two near-identical pipelines
Golf Swing Evaluation and Intro to Golf Evaluation each run through their own Flow + function pair rather than one shared one — same logic, only the product-name string and one early-return line differ.
Referral evals skip payment entirely
A Status=Referral booking (comp'd via an existing member) goes straight to a GolfManager booking with no Checkout charge, no Books invoice and no Credits record.
The AED 99 eval is tracked as a Credit, like a lesson package
The same GolfManager voucher/pay mechanism used for lesson-package credits is reused to mark the eval slot as paid, and a matching CRM Credits record (Balance 1) is created for it.
Every eval also becomes a Sales Pipeline Deal
sfaEvalSpineLink finds-or-creates a Deal at stage "Evaluation/Intro Booked & Paid" for the player, so the eval shows up in the sales pipeline the moment it's linked.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (21)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Zoho Checkout - Zoho CRM469029000000222003 | flow | Active | Zoho Checkout order created none (native connector actions only) | Upserts the CRM Contact and creates an Evaluation_Booking record (Status=Pending) with the chosen resource/coach, Start/End time and Price. Native Zoho-to-Zoho connector flow with no custom function, so its internal node logic is not readable from the archive, only its effect. | Zoho Flow > folder "Zoho Checkout - Zoho CRM" n/a - native flow, no Deluge source |
evaluationbookingconfirm6296422000051001824 | workflow rule | Active last run 2026-10-11T14:30 | Evaluation_Booking create none (unconditional) | Runs function evaluationbookingconfirm which sends the pre-session intake invite email. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking crm_deluge_source/evaluationbookingconfirm.deluge |
evaluationbookingconfirm1446733000000749001 | function | Active last run 2026-09-22T21:50 | called by workflow rule evaluationbookingconfirm n/a | Builds the ~5,000-char inline HTML intake-invite email and posts it via CRM send_mail (org_email:true) to the Evaluation_Booking. testMode is hardcoded "true" (line 94) with an unused goLive="2026-08-25T00:00:00" variable (line 97, never checked), so toAddr is always overridden to max@swingfitacademies.com regardless of goLive. On a non-SUCCESS send_mail response it emails max@ directly (native Deluge sendmail, not the CRM API) with subject "sfaEvalInviteAppPath EMAIL SEND FAILED". | CRM Setup > Automation > Functions crm_deluge_source/evaluationbookingconfirm.deluge |
Evaluation_Booking_ZohoFlow_EvaluationBookingZCRM6296422000049101001 | workflow rule | Active last run 2026-10-04T15:10 | Evaluation_Booking create or edit none (unconditional) | System webhook rule auto-generated by Zoho Flow to fire the flow "EvaluationBookingZCRM - Meta" (already documented above) whenever an Evaluation_Booking record is created or edited. Not user-editable/deletable from CRM Workflow Rules; managed from the Flow side. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking (created by Zoho Flow, not editable in CRM) n/a (Zoho Flow system webhook, no Deluge source; see EvaluationBookingZCRM - Meta / EvaluationBookingZCRM_Meta.deluge above) |
Eval Carry-Forward - App Path6296422000052122168 | workflow rule | Active last run 2026-10-09T14:37 | Evaluation_Booking create Source equals "App" | Runs function sfaEvalCarryForwardAppPath (Task 4, built 2026-08-29) which carries forward the player's self-reported Player_Roadmap answers (Route, Time_in_Dubai, What_makes_it_worth_it, Eval_Type) onto the new Evaluation_Booking record, skipping any booking whose Intake_completed is already true. It is the App-path counterpart to sfaEvalSpineLink's Section 2 carry-forward block for the GolfManager path - the App path creates the booking via an external REST call so normal create-trigger workflow rules fire, unlike the GolfManager path. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking crm_deluge_source/sfaevalcarryforwardapppath.deluge (6,501 chars, read in full) |
Zoho Checkout to ZCRM/GM - GolfSwing Evaluation469029000000311001 | flow | Active | Zoho Checkout payment success webhook Golf Swing Evaluation product line | Calls function ZCRM_UpdatePaymentStatus_GMBookingCreation. | Zoho Flow > folder "Zoho Checkout - Zoho CRM" n/a (flow shell; logic is in the called function) |
ZCRM_UpdatePaymentStatus_GMBookingCreation469029000000319001 | function | Active | called by flow "Zoho Checkout to ZCRM/GM - GolfSwing Evaluation" n/a | Finds the Contact by email, finds the Pending Evaluation_Booking, sets Status=Confirmed, finds-or-creates the GM customer, POSTs the booking to GM /api/model/booking, recharges a GM voucher and pays it via /api/billing/paySales, creates matching CRM Credits records for any package top-ups on the same invoice, and posts a "New Booking" alert to Cliq. Contains the GolfManager API key hardcoded in cleartext (redacted in the archive capture). | Zoho Flow > folder "Zoho Checkout - Zoho CRM" > function flow_deluge_source/ZCRM_UpdatePaymentStatus_GMBookingCreation.deluge (13,362 chars) |
ZCheckout to ZCRM/GM - Intro to Golf469029000000321205 | flow | Active | Zoho Checkout payment success webhook Intro to Golf Evaluation product line | Calls function CRM_UpdatePayStatus_GMBookingCreation - a near-duplicate of the GolfSwing Evaluation path. | Zoho Flow > folder "Zoho Checkout - Zoho CRM" n/a (flow shell) |
CRM_UpdatePayStatus_GMBookingCreation469029000000321212 | function | Active | called by flow "ZCheckout to ZCRM/GM - Intro to Golf" n/a | Line-for-line the same logic as ZCRM_UpdatePaymentStatus_GMBookingCreation except the hardcoded product-name string and one early-return line differ. Also carries the GolfManager API key hardcoded in cleartext. | Zoho Flow > folder "Zoho Checkout - Zoho CRM" > function flow_deluge_source/CRM_UpdatePayStatus_GMBookingCreation.deluge (13,140 chars) |
PaymentFailed - GolfSwing Evaluation469029000000311056 | flow | Active | Zoho Checkout payment failure webhook Golf Swing Evaluation product | Calls function Zcliq_PaymentFailed_Golf_Swing_Evaluation, which only posts a "Payment Failed" Cliq alert; it does not touch the Evaluation_Booking's Status or notify the customer. | Zoho Flow > folder "Zoho Checkout - Zoho CRM" flow_deluge_source/Zcliq_PaymentFailed_Golf_Swing_Evaluation.deluge (2,831 chars) |
PaymentFailed - Intro to Golf469029000000311036 | flow | Active | Zoho Checkout payment failure webhook Intro to Golf Evaluation product | Calls function ZcliqMsg_PaymentFailed_intro_to_golf_, same behaviour as the GolfSwing Evaluation payment-failed path. | Zoho Flow > folder "Zoho Checkout - Zoho CRM" flow_deluge_source/ZcliqMsg_PaymentFailed_intro_to_golf_.deluge (2,820 chars) |
sfaevalspinelink6296422000050977042 | workflow rule | Active last run 2026-10-11T17:49 | Bookings create/edit Resource_Name contains "Evaluation" AND Booking_Details contains "Evaluation" (live criteria as of 2026-09-11; the 2026-09-02 archive copy only had the Resource_Name condition - the AND was added later, see fix_additions) | Runs function sfaEvalSpineLink. | CRM Setup > Automation > Workflow Rules > Bookings crm_deluge_source/sfaevalspinelink.deluge |
sfaEvalSpineLink1446733000000742002 | function | Active last run 2026-09-23T09:29 | called by workflow rule sfaevalspinelink n/a | Matches the new GM-mirrored Bookings record back to the correct Evaluation_Booking (by GM booking id, or same player + same calendar day), stamps GM_Booking_Id and Source=GolfManager, finds-or-creates a Sales Pipeline Deal at stage "Evaluation/Intro Booked & Paid", carries forward earlier Player_Roadmap answers, and - only if no invite has been sent yet on this or a duplicate record for the same player/day - sends the same intake-invite email as a second path. testMode is hardcoded "true" here too. 2026-10-06 (v3): before writing anything it asks GolfManager which resource the booking is on; if not an Evaluation, nothing is created (no eval, Deal or invite). New eval records are named with the GolfManager resource name; the update branch no longer overwrites Source, so app-created bookings stay Source=App. | CRM Setup > Automation > Functions crm_deluge_source/sfaevalspinelink.deluge (13,968 chars) |
coachevaluationsweep6296422000050933008 | workflow rule | Active last run 2026-10-11T14:30 | Evaluation_Booking create/edit none (unconditional) | Runs function coachevaluationsweep (sfaEvalCoachOwnerStamp1) which matches the booking's resource string against a hardcoded list of 6 named coaches and sets record Owner to the matched coach's user id. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking crm_deluge_source/coachevaluationsweep.deluge (2,280 chars) |
EvaluationBookingZCRM - Meta469029000000330001 | flow | Active | Evaluation_Booking create UTM_Source == "meta_ads" (checked in the called function) | Calls function EvaluationBookingZCRM_Meta, which hashes the player's email/phone (SHA-256) and POSTs a "schedule" event (value AED 99, currency aed) to the Meta Conversions API for pixel 4473134646297796. | Zoho Flow > folder "Zoho - Meta" flow_deluge_source/EvaluationBookingZCRM_Meta.deluge (2,691 chars) |
ReferralEvaluationBooking6296422000049104068 | workflow rule | Active last run 2026-10-06T22:23 | Evaluation_Booking create/edit Status equals "Referral" | Runs function ReferralEvaluationBooking. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking crm_deluge_source/referralevaluationbooking.deluge |
ReferralEvaluationBooking1446733000000702010 | function | Active last run 2026-09-20T15:22 | called by workflow rule ReferralEvaluationBooking n/a | Finds-or-creates the friend as a GM customer, POSTs the GM booking for the evaluation slot, recharges GM voucherType 264 ("Golf Swing - Evaluation", amount 1) via /api/vouchers/recharge.json so the booking shows paid from credit, and creates a matching CRM Credits record (Balance 1). Also carries the GolfManager API key hardcoded in cleartext. | CRM Setup > Automation > Functions crm_deluge_source/referralevaluationbooking.deluge (5,158 chars) |
Coach Pre-Session Briefing Sweep6296422000051420046 | workflow rule | Active last run 2026-10-11T10:01 | date/time-based: 1 day before Start_Date_and_Time, execute_at 10:00:00+04:00, once none (unconditional) | Runs function sfaevalbriefingsendtest, which posts a "BEFORE YOU WALK IN" Cliq DM to the assigned coach with the player's intake answers and a Game Plan Builder link. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking crm_deluge_source/sfaevalbriefingsendtest.deluge (10,668 chars) |
sfaEvalIntakeBackstop6296422000052315007 | schedule | Active last run 2026-09-02T10:15 | hourly, every 2h, anchored at :15 (per schedules_live.tsv frequency "hourly/every2h") scans Evaluation_Booking where Intake_completed = false | R0: catch-up send of the intake invite (same HTML/subject as evaluationbookingconfirm) to bookings that haven't had it yet. R1: if not just sent this run and hoursToSession <= 48, sends the shorter "Still time" nudge instead. R2: stamps a Member-Success call-list flag. testMode is hardcoded "true" in this function too (no goLive override present in the source read this session), same org_email:true send_mail pattern, same max@ failure-notice pattern on non-SUCCESS. | CRM Setup > Automation > Schedules crm_deluge_source/sfaevalintakebackstop.deluge (16,258 chars) |
Coach Post-Session Debrief Send6296422000052132373 | workflow rule | Active last run 2026-10-11T16:00 | date/time-based: at End_Date_and_Time, once none (unconditional) | Runs function sfaEvalDebriefSend, which sends the coach a prefilled debrief-form link via Cliq DM. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking crm_deluge_source/sfaevaldebriefsend.deluge (7,719 chars) |
Evaluation Tracking469029000000009001 | flow | Inactive/draft | n/a - disabled n/a | Disabled flow (is_disabled=true, flow_status=0), created and last modified the same day (2026-02-13). No execution evidence and no other reference to it in this trace. | Zoho Flow > folder "default" n/a - archive could not open its node graph |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Evaluation_Booking | Status | Pending / Confirmed / Referral - drives which payment/comp branch runs | native Checkout-CRM flow (Pending); ZCRM_UpdatePaymentStatus_GMBookingCreation / CRM_UpdatePayStatus_GMBookingCreation (Confirmed); upstream process (Referral) |
| Evaluation_Booking | GM_Booking_Id | Links the CRM record to its GolfManager booking id | sfaEvalSpineLink |
| Evaluation_Booking | Source | Set to "GolfManager" once the GM-mirrored Bookings record links back | sfaEvalSpineLink |
| Evaluation_Booking | Owner | Set to the matching coach's CRM user | coachevaluationsweep (sfaEvalCoachOwnerStamp1) |
| Evaluation_Booking | Evaluation_Booking_Intake_Invite_Sent | Stamped true once an intake-invite send is attempted (attempt only, not delivery) | evaluationbookingconfirm / sfaEvalSpineLink / sfaEvalIntakeBackstop |
| Evaluation_Booking | Intake_Nudge_Sent | Stamped true once the backstop nudge (R1) has sent | sfaEvalIntakeBackstop |
| Evaluation_Booking | Intake_completed | True once the player has filled the 9-question intake form | the intake form's own save endpoint (not traced in this pass) |
| Bookings | Resource_Name / Booking_Details | Text fields the sfaevalspinelink criteria matches on to identify an eval booking | GM->CRM Bookings sync (untraced native flow) |
| Contacts | Credits (related list) | Balance-1 credit record mirroring the GM voucher for the eval | ZCRM_UpdatePaymentStatus_GMBookingCreation / CRM_UpdatePayStatus_GMBookingCreation / ReferralEvaluationBooking |
Full email text
Intake backstop - catch-upTwo minutes now makes the hour better
Intake backstop - nudgeStill time -- two quick minutes before your evaluation
IDs and references
| What | Value |
|---|---|
| Meta pixel | 4473134646297796 |
| GolfManager voucherType - Golf Swing Evaluation credit | 264 |
| GolfManager API base URL | https://eu.golfmanager.com/api (model/booking, billing/paySales, vouchers/recharge.json) |
| GolfManager API key | REDACTED - hardcoded in cleartext in ZCRM_UpdatePaymentStatus_GMBookingCreation.deluge, CRM_UpdatePayStatus_GMBookingCreation.deluge and referralevaluationbooking.deluge |
| Zoho Flow folder - Checkout/CRM/GM chain | 469029000000222001 ("Zoho Checkout - Zoho CRM") |
| Zoho Flow folder - Meta | 469029000000229056 ("Zoho - Meta") |
All flows › Sales pipeline
How a prospect moves through the sales pipeline (Deals)
Deals track a prospect from a booked evaluation through needs analysis, roadmap and follow-up to Closed Won, gated by a blueprint and cross-checked against billing.
- Starts when
- A Bookings record is created in CRM for a resource whose name contains "Evaluation" (fed from a GolfManager tee-sheet booking).
- Covers
- Covers the Deals module's Sales Pipeline: how a Deal gets created off an Evaluation booking, how it is kept in sync with the evaluation and roadmap steps, the blueprint that gates its stages, the daily follow-up nudge, and the billing check that runs on Closed Won. Does not cover the evaluation-booking or roadmap-capture flows themselves in full (see their own pages), sales-team routines (owner call-log tasks, notes, Dubai qualify/un-qualify), or coach calendars.
- Systems
- Zoho CRM, GolfManager, Zoho Books
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Eval booking createdGolfManager
A customer books a swing evaluation
From codeThe booking is made on the GolfManager tee sheet and lands in CRM as a Bookings record whose Resource_Name names an Evaluation resource (e.g. a named coach's evaluation slot).
See itCRM > Bookings, filter Resource_Name contains "Evaluation" - T+0Spine link firesZoho CRM
The booking triggers the eval-to-Deal spine function
Verified liveThe
sfaevalspinelinkworkflow rule (create trigger on Bookings, criteria: Resource_Name contains "Evaluation") runs thesfaEvalSpineLinkfunction. It finds or creates the matching Evaluation_Booking record for this booking (by GolfManager booking id, or by same Player + same day).- Real exampleVerified liveT+0
A booking from the week of 19-22 Sep 2026 resolved to its own Evaluation_Booking and a linked Deal, created seconds after the booking record itself.
See itEvaluation_Booking module, GM_Booking_Id field - T+0 (same run)Deal found or createdZoho CRM
sfaEvalSpineLink finds or creates the Deal
Verified liveStill inside
sfaEvalSpineLink, the function looks at the Contact's existing Deals for one already sitting in the "Sales Pipeline" pipeline that isn't Closed Won or Closed Lost. If it finds one, it links this Evaluation_Booking to it and sets Stage back to "Evaluation/Intro Booked & Paid". If it finds none, it creates a new Deal named "<Contact> - Evaluation", Pipeline "Sales Pipeline", Stage "Evaluation/Intro Booked & Paid", Deal_Type "Prospect", Closing_Date 45 days out.- Real exampleVerified live
128 Deals currently sit in the Sales Pipeline, all created this way; the most recent (created 22 Sep 2026, Pipeline Sales Pipeline, Stage Evaluation/Intro Booked & Paid) matches a booking from the same day.
See itDeals module, filter Contact_Name = the player and Pipeline = Sales Pipeline - T+0 (Deal create trigger)Default owner setZoho CRM
A new Deal gets a default owner
Verified live"Auto-assign Owner to Member Success @ SFA" (create trigger on Deals, native field-update action, no custom function) sets Owner to the shared "Member Success @ SFA" account on every new Deal. A real staff member is meant to pick the Deal up and reassign Owner to themselves.
See itDeal record, Owner field - on Owner changeOwner reassignedZoho CRM
Reassigning Owner mirrors onto Sales_Person or Coaching
Unverified"Deal Owner Sync - Sales_Person/Coaching" (field_update on Owner, any value, repeat on, scoped to Pipeline = Sales Pipeline) runs
sfaDealOwnerSync. If the new Owner's email matches a Coaches record it writes that record into Coaching; if it matches a Sales_Staff record it writes them into Sales_Person. The shared Member Success owner, or any owner matching neither list, is left as-is.See itDeal record, Coaching / Sales_Person fields - on Intake_completed = trueNeeds analysis synced (G1)Zoho CRM
Needs-analysis completion syncs onto the Deal
Unverified"G1 - Needs Analysis Complete Sync to Deal" (field_update on Evaluation_Booking, criteria Intake_completed = true) runs
sfaSyncNeedsAnalysisToDeal. It looks up the Deal linked to that Evaluation_Booking and, only if the Deal is in Sales Pipeline and not already "Completed", sets Needs_Analysis_Status to "Completed".See itDeal record, Needs_Analysis_Status field - on Player_Roadmap createRoadmap synced (G2)Zoho CRM
A captured roadmap syncs onto the Deal
Verified live"G2 - Roadmap Capture Sync to Deal" (create trigger on Player_Roadmap) runs
sfaSyncRoadmapCaptureToDeal. It finds the Contact's Deal in Sales Pipeline and, if Roadmap_Captured isn't already true, sets it to true.- Real exampleVerified live
Several Deals created 19-22 Sep 2026 already show Roadmap_Captured = true, matching a Player Roadmap record captured for that same contact the same day.
See itDeal record, Roadmap_Captured field - always (stage-transition check)Blueprint gates the stageZoho CRM
The Sales Pipeline Gating blueprint controls how far a Deal can move
UnverifiedAn active blueprint on Deals.Stage, built 30 August 2026, requires Needs_Analysis_Status to be Completed before a Deal can move past "Needs Analysis Sent", and requires Roadmap_Captured to be true before a Deal can be marked "Closed Won". It runs whenever a staff member tries to change the Stage of a Sales Pipeline Deal.
See itOpen a Deal in the pipeline Kanban view and try to move it to the next stage; the blueprint's transition checklist shows what's still required - manual, staffDeal moved to FollowUpZoho CRM
A worked Deal can be moved into the follow-up track
UnverifiedOnce needs analysis and later stages have been worked, a staff member sets the Deal's Stage to "FollowUp" by hand to hand it to the automated nudge sequence below.
See itDeal record, Stage field - daily 09:30 Asia/DubaiFollow-up nudge sweepZoho CRM
A daily sweep nudges Deals sitting at FollowUp
UnverifiedThe
sfaFollowUpSweep_Dailyschedule runssfaFollowUpSweepdaily. For every Deal at Stage = "FollowUp" it checks the linked Contact's Lifecycle_Status / RE_P_Stage, then steps FollowUp_Stage forward (0 to 1 immediately, then 2 and 3 each after 7+ days) and sends the matching templated email: a first re-engage note, then a Studio City- or DIFC-specific note naming that location's coach. It stamps FollowUp_Stage, FollowUp_Stage_Changed and Last_FollowUp_Sent on the Deal each time.See itDeal record, FollowUp_Stage / Last_FollowUp_Sent fields; Contact's Emails related list for the sent copy - on Stage = Closed WonWon billing verifiedZoho CRM
Marking a Deal Closed Won triggers a billing cross-check
Unverified"Verify Won Billing" (field_update on Stage = "Closed Won", scoped to Sales Pipeline) runs
sfaVerifyWonBilling. It looks for a live Membership on the Deal's Contact; if there isn't one, it checks Zoho Books (Studio City org) for a paid invoice under that contact's email. It then stamps Billing_Verification ("Verified" or "Unverified - Needs Review"), Books_Verification, an Amount, and, for a PAYG sale, an Internal_Comment listing the invoice's line items.See itDeal record, Billing_Verification / Books_Verification / Amount fields - on Membership create, within 30 days of a matching evalConversion stamped (parallel path)Zoho CRM
A separate stamp records that an evaluation converted
Unverified"Converted Evaluation Stamp" (create trigger on Memberships) runs
sfaConvertedEvalOnMembership. When a new Membership follows a qualifying evaluation Booking (by keyword match) within 30 days, and that booking already has a Lesson_Report, it stamps that Lesson_Report's Session_Category as "Converted Evaluation". This writes to the Lesson_Report, not to the Deal, so it runs alongside the Deal steps above rather than through them.See itLesson_Reports module, Session_Category field - on Contact create/edit with GS_Marketing_Campaign = "10 Day Trial"10-Day-Trial Deal (legacy path)Zoho CRM
A separate Deal path exists for the 10-Day-Trial campaign
Unverified"Create Deal for 10 Days Trial" (create/edit trigger on Contacts, criteria GS_Marketing_Campaign = "10 Day Trial") is designed to create a Deal at Stage "Day 1" under a separate SFA 2.0 layout, owned by a fixed user rather than the Sales Pipeline default. A companion function is designed to step the Deal from Day 1 through Day 10 and then to "10 for 10 Expired LOST" after 24 hours in each stage.
See itDeals module, Stage = Day 1 through Day 10, or 10 for 10 Expired LOST
Emails and messages
CustomerTwo minutes now makes the hour betterVerified liveTwo minutes now makes the hour better
Full text ($HOME/arch/crm_deluge_source/sfaevalspinelink.deluge (inline HTML string in the function body))
CustomerFollowUp-E1-ReengageUnverifiednot confirmed in this pass - referenced by CRM template id only
Full text (not found - searched crm_email_templates/ for this template id and for a Reengage/FollowUp-named file; only a differently-worded RE-P-E1_Pick-Up-Where.html exists, referenced from a separate re-engagement build (Phase C), not confirmed as the same template id)
CustomerFollowUp-E2-Coach1 (Studio City / DIFC variants)Unverifiednot confirmed in this pass - referenced by CRM template id only
CustomerFollowUp-E3-Coach2 (Studio City / DIFC variants)Unverifiednot confirmed in this pass - referenced by CRM template id only
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Which Deal is a given evaluation tied to? | Deals module, search by Contact_Name, or open the Evaluation_Booking and follow its Deals related list | One Deal in Sales Pipeline, Stage matching how far the prospect has actually progressed |
| Did the needs-analysis step sync onto the Deal? | Deal record, Needs_Analysis_Status field | Shows "Completed" once intake is marked done on the linked Evaluation_Booking |
| Did the roadmap capture sync onto the Deal? | Deal record, Roadmap_Captured field | Flips to true once a Player_Roadmap record exists for that contact |
| Is a Deal ready to move past Needs Analysis Sent, or to Closed Won? | Try the stage move in the pipeline Kanban view | The blueprint lets the move through once Needs_Analysis_Status / Roadmap_Captured are set; otherwise it explains what's missing |
| Did billing get checked after a Deal was marked Closed Won? | Deal record, Billing_Verification / Books_Verification / Amount fields | Billing_Verification reads "Verified" with an Amount filled in, or "Unverified - Needs Review" if no live Membership or paid Books invoice was found |
| Is a Deal being followed up on? | Deal record, FollowUp_Stage and Last_FollowUp_Sent fields | FollowUp_Stage steps up roughly weekly while the Deal sits at Stage = FollowUp |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Deal creation off an evaluation booking | CRM Setup > Automation > Workflow Rules > Bookings > sfaevalspinelink | stops the intake-invite email AND stops new Deals being created or linked from evaluation bookings |
| Owner mirroring onto Sales_Person / Coaching | CRM Setup > Automation > Workflow Rules > Deals > Deal Owner Sync - Sales_Person/Coaching | Owner can still be changed by hand, but Sales_Person / Coaching will no longer follow it automatically |
| Needs-analysis sync | CRM Setup > Automation > Workflow Rules > Evaluation Booking > G1 - Needs Analysis Complete Sync to Deal | Needs_Analysis_Status on the Deal will have to be set by hand, and the blueprint's Needs Analysis Sent gate will then never clear automatically |
| Roadmap sync | CRM Setup > Automation > Workflow Rules > Player Roadmap > G2 - Roadmap Capture Sync to Deal | Roadmap_Captured on the Deal will have to be set by hand, and the blueprint's Closed Won gate will then never clear automatically |
| Follow-up nudge emails | CRM Setup > Automation > Schedules > sfaFollowUpSweep_Daily | stops the daily FollowUp email sequence; Deals already at Stage = FollowUp simply stop moving forward |
| Won-billing check | CRM Setup > Automation > Workflow Rules > Deals > Verify Won Billing | Closed Won Deals will no longer be checked against Memberships or Books automatically |
Good to know
One pipeline, many old stage names
The Deals module's Stage field carries dozens of picklist values left over from earlier pipeline designs. Only "Sales Pipeline" and its blueprint stages (Evaluation/Intro Booked & Paid, Needs Analysis Sent, FollowUp, Closed Won, Closed Lost, and the others the blueprint defines) are live for this flow.
A Deal always starts life the same way
Every Sales Pipeline Deal is named "<Contact> - Evaluation", starts at Stage "Evaluation/Intro Booked & Paid", Deal_Type "Prospect", and gets a Closing_Date 45 days out, owned by the shared Member Success account until someone picks it up.
Duration fields track how long a Deal has been open
Stage_Start_Time records when the current stage began; Overall_Sales_Duration and Sales_Cycle_Duration track total time in days since the Deal was created.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (12)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
sfaevalspinelink6296422000050977042 | workflow rule | Active last run 2026-10-11T17:49 | create Resource_Name contains "Evaluation" | Finds or creates the matching Evaluation_Booking record, then finds-or-creates a Deal in Sales Pipeline for the Contact (Section 1.5), carries forward any prior Player_Roadmap answers onto the Evaluation_Booking, and sends the intake-invite email if not already sent. | Setup > Automation > Workflow Rules > Bookings $HOME/arch/crm_deluge_source/sfaevalspinelink.deluge |
Auto-assign Owner to Member Success @ SFA6296422000051925021 | workflow rule | Active last run 2026-10-11T17:04 | create none (fires on every new Deal) | Native field-update instant action; sets Owner to the shared Member Success @ SFA user (id 6296422000002537001) on every newly created Deal. | Setup > Automation > Workflow Rules > Deals n/a - native field-update action, no Deluge function |
Deal Owner Sync - Sales_Person/Coaching6296422000051978013 | workflow rule | Active last run 2026-08-28T16:04 | field_update on Owner (any value, repeat: true) Pipeline = Sales Pipeline | Runs sfaDealOwnerSync: if the new Owner's email matches a Coaches record, writes it into Coaching; else if it matches a Sales_Staff record, writes it into Sales_Person. Owner = Member Success or no match: no-op, never clears an existing value. | Setup > Automation > Workflow Rules > Deals $HOME/arch/crm_deluge_source/sfadealownersync.deluge |
G1 - Needs Analysis Complete Sync to Deal6296422000052122151 | workflow rule | Active last run 2026-08-29T13:11 | field_update Intake_completed = true | Runs sfaSyncNeedsAnalysisToDeal: finds the Deal related to this Evaluation_Booking, and if it is in Sales Pipeline and not already Completed, sets Needs_Analysis_Status = Completed. | Setup > Automation > Workflow Rules > Evaluation Booking $HOME/arch/crm_deluge_source/sfasyncneedsanalysistodeal.deluge |
G2 - Roadmap Capture Sync to Deal6296422000052122160 | workflow rule | Active last run 2026-08-29T13:11 | create none | Runs sfaSyncRoadmapCaptureToDeal: reads the Player_Roadmap's Player (Contact), finds their Deal via the Deals-Contacts related list, and if it is in Sales Pipeline and Roadmap_Captured isn't already true, sets it to true. Skips lead-only roadmaps with no Contact. | Setup > Automation > Workflow Rules > Player Roadmap $HOME/arch/crm_deluge_source/sfasyncroadmapcapturetodeal.deluge |
Sales Pipeline Gating (blueprint)unknown - blueprint id not retrievable via the read-only CRM tools available | other | Active | stage transition attempt on a Sales Pipeline Deal past "Needs Analysis Sent": requires Needs_Analysis_Status = Completed. into "Closed Won": requires Roadmap_Captured = true. | Blocks the stage move in the UI/API until the listed field condition is met; built 30 Aug 2026 per the internal automation-estate review. | Setup > Process Management > Blueprints, module Deals, field Stage n/a - configured in Blueprint Designer, not Deluge; documented in estate.txt lines 895-916 |
sfaFollowUpSweep_Daily6296422000052141002 | schedule | Active last run 2026-09-02T09:45 | daily 09:30 Asia/Dubai Deals where Stage = FollowUp; Contact Lifecycle_Status/RE_P_Stage gate; FollowUp_Stage < 3; 7+ days since FollowUp_Stage_Changed for steps 2 and 3 | Runs sfaFollowUpSweep: advances FollowUp_Stage (0->1->2->3) and sends the matching templated email (location-specific for steps 2 and 3), then stamps FollowUp_Stage, FollowUp_Stage_Changed and Last_FollowUp_Sent on the Deal. | Setup > Automation > Schedules $HOME/arch/crm_deluge_source/sfafollowupsweep.deluge |
Verify Won Billing6296422000052141060 | workflow rule | Active last run 2026-08-31T17:52 | field_update Stage = Closed Won; Pipeline = Sales Pipeline | Runs sfaVerifyWonBilling: checks for a live Membership on the Deal's Contact; if none, queries Zoho Books (org 866469739) for a paid invoice by that contact's email, then stamps Billing_Verification, Books_Verification, Amount, and (for PAYG) Internal_Comment with the invoice's line items. | Setup > Automation > Workflow Rules > Deals $HOME/arch/crm_deluge_source/sfaverifywonbilling.deluge |
Converted Evaluation Stamp6296422000048825187 | workflow rule | Inactive last run 2026-08-05T17:33 | create none (function applies its own 30-day window + keyword match) | Runs sfaConvertedEvalOnMembership: finds a qualifying evaluation Booking (keyword match on Booking_Details) in the 30 days before the new Membership's start date, and if that Booking already has a Lesson_Report with no Session_Category set, stamps it "Converted Evaluation". Writes to Lesson_Reports, not to the Deal. | Setup > Automation > Workflow Rules > Memberships $HOME/arch/crm_deluge_source/sfaconvertedevalonmembership.deluge |
Create Deal for 10 Days Trial6296422000039302104 | workflow rule | Inactive last run 2026-05-06T16:21 | create_or_edit GS_Marketing_Campaign = "10 Day Trial" | Runs Create_Deal_for_10_Days_Trial: creates a Deal named after the Contact, Stage "Day 1", Layout id 6296422000000091023, Owner fixed to user 6296422000002537001, Stage_Start_Time = now. Pipeline is not set explicitly by this function. | Setup > Automation > Workflow Rules > Contacts $HOME/arch/crm_deluge_source/create_deal_for_10_days_trial.deluge |
Update Deal Stage for - 10 Days Trial1446733000000546003 (function id; no live schedule id found) | schedule | Inactive | designed to run periodically over all Deals Stage in Day 1..Day 10 and Stage_Start_Time more than 24 hours old | Steps the Deal's Stage forward one day (Day 1 -> Day 2 ... Day 10 -> "10 for 10 Expired LOST") and resets Stage_Start_Time. | Setup > Automation > Schedules (not currently present in the live schedule list) $HOME/arch/crm_deluge_source/update_deal_stage_for_10_days_trial.deluge |
ZZOFF-2026-09 Lead to Prospect6296422000012924110 | workflow rule | Inactive last run 2026-09-09T15:04 | create unknown - deactivated before this pass | Deactivated and renamed during the 09 Sep 2026 exit-handover mass switch-off; not currently part of the live Deal-creation path. | Setup > Automation > Workflow Rules > Deals n/a |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Deals | Stage | current pipeline stage; gated by the Sales Pipeline Gating blueprint | sfaEvalSpineLink (initial), staff (manual moves), blueprint transitions |
| Deals | Pipeline | which pipeline the Deal belongs to; automations only act on Pipeline = Sales Pipeline | sfaEvalSpineLink on create |
| Deals | Owner | CRM record owner; defaults to the shared Member Success user | Auto-assign Owner to Member Success @ SFA; staff reassignment |
| Deals | Sales_Person | linked Sales_Staff record once Owner is reassigned to a salesperson | sfaDealOwnerSync |
| Deals | Coaching | linked Coaches record once Owner is reassigned to a coach | sfaDealOwnerSync |
| Deals | Needs_Analysis_Status | whether the intake/needs-analysis step is done; blocks progress past Needs Analysis Sent | sfaSyncNeedsAnalysisToDeal (G1) |
| Deals | Roadmap_Captured | whether a Player_Roadmap exists for the contact; blocks Closed Won | sfaSyncRoadmapCaptureToDeal (G2) |
| Deals | Billing_Verification | post-Closed-Won billing check result: Verified / Unverified - Needs Review | sfaVerifyWonBilling |
| Deals | Books_Verification | detail of which Books check matched (Verified Membership / Verified PAYG) | sfaVerifyWonBilling |
| Deals | Amount | deal value, back-filled from the matched membership tier or Books invoice total | sfaVerifyWonBilling |
| Deals | Internal_Comment | free text noting the matched Books invoice and line items for a PAYG sale | sfaVerifyWonBilling |
| Deals | FollowUp_Stage | 0-3 counter of how many follow-up emails have gone out | sfaFollowUpSweep |
| Deals | FollowUp_Stage_Changed | timestamp of the last FollowUp_Stage change, used to gate the next 7-day step | sfaFollowUpSweep |
| Deals | Last_FollowUp_Sent | date of the most recent follow-up email | sfaFollowUpSweep |
| Deals | Eval_Booking | lookup to the linked Evaluation_Booking record | sfaEvalSpineLink |
| Deals | Deal_Type | defaults to Prospect on creation | sfaEvalSpineLink |
| Deals | Stage_Start_Time | when the Deal entered its current stage | Create_Deal_for_10_Days_Trial (legacy path); not set by sfaEvalSpineLink on the Sales Pipeline path |
| Evaluation_Booking | Intake_completed | flips true once the player finishes the intake form; triggers G1 | sfaEvalSpineLink (carry-forward) or the public intake form |
| Player_Roadmap | Player | lookup to the Contact; if blank the roadmap is lead-only and G2 skips it | roadmap capture form/flow (outside this trace) |
Full email text
FollowUp-E2-Coach1-StudioCitynot found
FollowUp-E2-Coach1-DIFCnot found
FollowUp-E3-Coach2-StudioCitynot found
FollowUp-E3-Coach2-DIFCnot found
IDs and references
| What | Value |
|---|---|
| Deals module id | 6296422000000002181 |
| Deals.Pipeline field id | 6296422000000193001 |
| Deals.Owner field id | 6296422000000002555 |
| Deals.Stage field id | 6296422000000002565 |
| Live Sales Pipeline value on Deals.Pipeline | Sales Pipeline |
| Default Deal owner (Member Success @ SFA) user id | 6296422000002537001 |
| 10-Day-Trial legacy Deal layout id | 6296422000000091023 |
| Zoho Books org (Studio City) used by sfaVerifyWonBilling | 866469739 |
| sfaEvalSpineLink intake-invite template reference (inviteTid var, unused - inline HTML sent instead) | 6296422000051001731 |
All flows › Referral
When a member refers a friend
A member's referral link comps the friend's evaluation in GolfManager, and the referrer earns a credit once the friend makes their first purchase.
- Starts when
- A member shares their personal Referral Factory link (refer.swingfitacademies.com, campaign 49133); the friend clicks it and is booked in for a free evaluation, which lands in CRM as an Evaluation_Booking with Status = Referral.
- Covers
- Covers capture of a Referral Factory referral through the friend's comped evaluation booking, the friend's first real purchase, and the referrer's GolfManager credit reward, plus the confirmation emails on both sides. Does not cover Referral Factory campaign/dashboard configuration itself or general lead-nurture emails unrelated to the referral tag.
- Systems
- Zoho CRM, Zoho Flow, GolfManager, Zoho Billing, Zoho Books, Zoho POS, Zoho Commerce, Referral Factory
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0friend books via referral linkWebsite
Friend clicks the referral link and books a free evaluation
Verified liveReferral Factory's tracked link (campaign 49133, refer.swingfitacademies.com) carries the referrer's identity through to the booking. The friend's resulting Contact record ends up with
RF_Referrer_EmailandRF_Referrer_First_Namepopulated, and their evaluation is booked withStatus = Referralon theEvaluation_Bookingrecord.See itCRM: open the friend's Contact, check theRF_Referrer_Email/RF_Referrer_First_Namefields under the referral section. - T+0 to T+2sReferralEvaluationBooking firesZoho CRM
CRM comps the friend's evaluation in GolfManager
Verified liveWorkflow rule
ReferralEvaluationBooking(Evaluation_Booking, create/edit, active) fires whenever Status = Referral and runs the Deluge function of the same name.- Find or create the friend in GolfManagerVerified liveT+0
Searches GM
customerby the friend's email; creates a new GM customer if none exists. - Create the comped booking in GolfManagerVerified liveT+0
Posts a GM
bookingfor the evaluation slot at the resource/coach chosen, price shown as the normal eval price (e.g. 99) but paid from credit, not cash. - Recharge a free-eval credit onto the friend's GM accountVerified liveT+0
Posts to GM
vouchers/rechargefor voucherType 264 ("Golf Swing - Evaluation"), amount 1, 60-day expiry — this is what zeroes out the booking's price at checkout. - Mirror the credit in CRMVerified liveT+0
Creates a
Creditsrecord (Name: "Golf Swing - Evaluation", Balance 1) on the friend's CRM Contact for internal visibility.
See itCRM Setup > Automation > Workflow Rules > Evaluation_Booking module >ReferralEvaluationBooking— Last Executed timestamp. - day of visitfriend attends + may buyGolfManager
Friend attends the comped evaluation
UnverifiedThe friend's eval is delivered as a normal booking. If they then buy a first package or membership, that sale creates a Zoho Books invoice either through Zoho Billing (a subscription) or through POS/Zoho Commerce (a one-off sale) — which path depends only on what they bought.
See itZoho Books: search the friend's email in Invoices (org 866469739 Studio City or 872210045 DIFC). - T+seconds after invoicereferrer credit flowZoho Flow
First purchase pays out the referrer's credit
From codeOne of two live webhook flows picks up the friend's first invoice:
ZBilling - ReferralFactoryfor a Zoho Billing (subscription) invoice, calling functionGM_UpdateReferrerCredits; orPOS/Commerce - CRM/Referralfactoryfor a POS/Commerce (one-off) invoice, calling functionUpdateReferrerCreditsInGolfManageer. Both functions run the same logic end to end.- Confirm this is the friend's first purchaseFrom codeT+0
Re-queries Books invoices for that customer_id; if more than one invoice already exists, the function stops — repeat purchases never re-trigger the referral payout.
- Match/convert the friend in CRMFrom codeT+0
Searches CRM Leads and Contacts by the friend's email; if both exist, converts the Lead into the existing Contact.
- Read the referrer off the friend's ContactFrom codeT+0
Pulls
RF_Referrer_EmailandRF_Referrer_First_Namefrom the friend's Contact record. - Recharge the referrer's GolfManager creditVerified liveT+0
Finds the referrer as a GM customer by email (creating one if missing) and recharges voucherType 245, amount 1, 60-day expiry, price 0.
- Qualify the friend in Referral FactoryFrom codeT+0
PUTs to the Referral Factory qualification API (campaign_id 49133, qualified: true) for the friend's email.
- Mirror the referrer's credit in CRMFrom codeT+0
Ensures a CRM Contact exists for the referrer (creating a "Prospect" Contact if none is found), then creates a
Creditsrecord on it matching the top-up item the friend's purchase earned.
See itZoho Flow > folder "Zoho - Referral Factory" > either flow > run history (transaction_count). - next visitreferrer redeemsGolfManager
Referrer spends their earned credit
UnverifiedThe recharged GM voucher sits on the referrer's account and is applied automatically the next time they book something it covers. No further automation runs.
See itGolfManager: referrer's customer record > Vouchers tab.
Emails and messages
CustomerSend email to the person who made the referralUnverified(template not opened this session — see template location)
Full text (not found)
CustomerConfirmation email to the Referred PersonUnverified(template not opened this session)
Full text (not found)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did my friend's eval get comped correctly? | GolfManager > friend's customer record > Vouchers tab | A voucher of type "Golf Swing - Evaluation" (id 264), balance 1, ~60 days from booking, and the eval booking itself shows price paid from credit not cash. |
| Did my referral credit come through? | GolfManager > referrer's customer record > Vouchers tab | A voucher type 245, amount 1 — but only appears AFTER the friend's first real purchase, not at eval-booking time. No purchase yet = no voucher yet, and that is expected. |
| Did the referrer/friend get a confirmation email? | CRM Setup > Automation > Workflow Rules > Leads > search "Referral Confirmation" | Rule shows Active and a recent Last Executed time, with a matching entry on the Emails related list. |
| Is this referral registered with Referral Factory? | Referral Factory dashboard, campaign 49133 | The friend shows as qualified once their first purchase has processed (their record shows a qualified=true state). |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Comping the friend's evaluation + GM booking creation | CRM Setup > Automation > Workflow Rules > Evaluation_Booking module > ReferralEvaluationBooking — deactivate | New referral evals stop getting auto-created/comped in GolfManager; the Evaluation_Booking record still gets created by whatever upstream process sets Status=Referral, but nothing acts on it. |
| Referrer's GolfManager credit + Referral Factory qualification | Zoho Flow > folder "Zoho - Referral Factory" > toggle off ZBilling - ReferralFactory and/or POS/Commerce - CRM/Referralfactory | New first-purchases by referred friends stop paying out a GM credit to the referrer and stop qualifying the friend in Referral Factory. Both flows must be turned off together to stop the whole payout path, since each only covers one purchase channel. |
| Referral confirmation emails | Already off — CRM Setup > Automation > Workflow Rules > Leads > ZZOFF-2026-09 Referral Confirmation | Turning it back on (renaming off the ZZOFF prefix and reactivating) resumes both the referrer's and the friend's confirmation emails. |
Good to know
Referral Factory owns the link, not the CRM
Campaign 49133 and the refer.swingfitacademies.com domain belong to Referral Factory; it is the source of each member's personal tracked link and the qualification status shown on their dashboard.
The friend's comp and the referrer's reward are two separate payouts
The friend's free evaluation is comped immediately at booking time (voucherType 264). The referrer's reward (voucherType 245) only fires once — on the friend's first REAL purchase — so a referrer sees nothing until their friend actually buys something, however long that takes.
Two flows, one job, split by payment channel
ZBilling - ReferralFactory handles first purchases that come through Zoho Billing (subscriptions); POS/Commerce - CRM/Referralfactory handles first purchases through POS or Zoho Commerce (one-off sales). They run the same referrer-credit logic because Billing and Books/POS invoices are fetched from different APIs.
No Meta or Cliq side effects found
Reading both referrer-credit functions in full, neither calls graph.facebook.com nor Zoho Cliq — the referral reward loop is CRM + GolfManager + Referral Factory only.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (8)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Referral Factory tracked linkcampaign 49133, refer.swingfitacademies.com | other | Active | friend clicks a member's personal referral link n/a | Carries the referrer's identity through to the booking; stamps the friend's CRM Contact with RF_Referrer_Email / RF_Referrer_First_Name once the booking lands. | Referral Factory dashboard (external SaaS, not a Zoho automation) n/a - external SaaS, not in the archive |
ReferralEvaluationBooking6296422000049104068 | workflow rule | Active last run 2026-10-06T22:23 | Evaluation_Booking create/edit Status equal "Referral" | Runs function ReferralEvaluationBooking. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking |
ReferralEvaluationBooking1446733000000702010 | function | Active last run 2026-09-20T15:22 | called by workflow rule ReferralEvaluationBooking n/a | Finds-or-creates the friend as a GM customer, POSTs the GM booking for the eval slot, recharges GM voucherType 264 ("Golf Swing - Evaluation", amount 1) via /api/vouchers/recharge.json (paid from credit, not cash), and creates a matching CRM Credits record (Balance 1) on the friend's Contact. Carries the GolfManager API key hardcoded in cleartext. | CRM Setup > Automation > Functions crm_deluge_source/referralevaluationbooking.deluge (5,158 chars, full body read) |
ZBilling - ReferralFactory469029000000258001 | flow | Active | Zoho Billing invoice webhook (subscription/membership first purchase) none at flow level - the called function checks first-purchase and referrer-present internally | Calls function GM_UpdateReferrerCredits. | Zoho Flow > folder "Zoho - Referral Factory" n/a (flow shell) |
POS/Commerce - CRM/Referralfactory469029000000257001 | flow | Active | Zoho Books invoice webhook (POS or Zoho Commerce one-off sale) none at flow level | Calls function UpdateReferrerCreditsInGolfManageer. | Zoho Flow > folder "Zoho - Referral Factory" n/a (flow shell) |
GM_UpdateReferrerCredits469029000000258009 | function | Active | called by flow ZBilling - ReferralFactory n/a in the function signature; internal logic gates on first-purchase and referrer-present | Re-queries Books invoices for the buying customer - if more than one already exists, stops (repeat purchases never re-trigger). Matches/converts the friend's Lead into their Contact. Reads RF_Referrer_Email/RF_Referrer_First_Name off the friend's Contact. If referrer_email is empty, logs "This Sale doesn't have a referrer" but the return; right after that check is commented out (line ~184), so execution falls through regardless. Finds-or-creates the referrer as a GM customer and recharges voucherType "245" (amount 1, 60-day expiry, price 0) via GM's voucher-recharge endpoint. PUTs the Referral Factory qualify endpoint (campaign_id "49133", qualified:true) for the friend's email. Ensures a CRM Contact exists for the referrer, creating a Lifecycle_Status="Prospect" Contact with Last_Name=referrer_firstname if none is found, then creates a matching Credits record on it. | Zoho Flow > folder "Zoho - Referral Factory" > function flow_deluge_source/GM_UpdateReferrerCredits.deluge (10,596 chars, full body read) |
UpdateReferrerCreditsInGolfManageer469029000000257008 | function | Active | called by flow POS/Commerce - CRM/Referralfactory n/a in signature; same internal gating as GM_UpdateReferrerCredits | Line-by-line identical logic to GM_UpdateReferrerCredits except it fetches the invoice from the Zoho Books API (not Zoho Billing) - including the same commented-out //return; on an empty referrer_email. | Zoho Flow > folder "Zoho - Referral Factory" > function flow_deluge_source/UpdateReferrerCreditsInGolfManageer.deluge (10,510 chars) |
Referral Confirmation6296422000008727025 | workflow rule | Inactive last run 2025-09-18T18:24 | Lead create Tag equal "Via Affiliate Program" | Two email-notification actions on the same rule: "Send email to the person who made the referral" (template "New Lead via Affiliate Program", id 6296422000008727009) and "Confirmation email to the Referred Person" (template "Confirmation email to the person who was referred", id 6296422000008727041). Both notifications' from_address is type "user", resource id 6296422000000479001 (Richard Dunsby's personal CRM user), not an org/brand address. | CRM Setup > Automation > Workflow Rules > Leads (currently "ZZOFF-2026-09 Referral Confirmation") n/a for the rule itself; email_notifications actions 6296422000008727016 and 6296422000008727048 hold the from-address/template wiring |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Contacts | RF_Referrer_Email / RF_Referrer_First_Name | Identifies who referred this Contact - read by both referrer-credit functions | Referral Factory tracked-link integration at booking time |
| Evaluation_Booking | Status | "Referral" marks a comped (no-payment) evaluation | upstream process that creates the booking from the Referral Factory link (not traced in this pass) |
| Contacts | Credits (related list) | Balance-1 record mirroring the GM voucher - one for the friend's comped eval (voucherType 264), one for the referrer's reward (voucherType 245) | ReferralEvaluationBooking (friend); GM_UpdateReferrerCredits / UpdateReferrerCreditsInGolfManageer (referrer) |
| Contacts | Lifecycle_Status | Set to "Prospect" when a referrer Contact has to be created from scratch (no existing CRM record) during the credit payout | GM_UpdateReferrerCredits / UpdateReferrerCreditsInGolfManageer |
IDs and references
| What | Value |
|---|---|
| Referral Factory campaign | 49133 (refer.swingfitacademies.com) |
| GolfManager voucherType - friend's comped eval | 264 ("Golf Swing - Evaluation") |
| GolfManager voucherType - referrer's reward | 245 |
| GolfManager API base URL | https://eu.golfmanager.com/api (customer, booking, vouchers/recharge) |
All flows › Online store
When someone buys a pack on the online store
The store takes payment, emails the customer, and within minutes the credits land in GolfManager and CRM.
- Starts when
- A customer checks out and pays on the online store (Zoho Commerce).
- Covers
- PAYG lesson packs, practice packs and single sessions bought through Zoho Commerce (Studio City only). Desk sales in POS share most of this chain and have their own flow.
- Systems
- Zoho Commerce, Zoho Books, Zoho Flow, GolfManager, Zoho CRM, Zoho Cliq
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0checkoutZoho Commerce
Customer pays on the online store
Verified liveCommerce creates a sales order (for example
SO-00468). Commerce is only switched on for the Studio City Books organization; DIFC sells through POS.See itCommerce › Orders - T+0secondsZoho Commerce
Customer gets two emails from the store
Verified live"Order Confirmed" and "Order Summary" are Commerce's own templates, sent from info@swingfitacademies.com. Rewritten on 22 Sep with our branding and a "Book your next session" button. Max confirmed on 23 Sep that both are going out.
See itCommerce › Orders › open the order. Templates: Settings › Customization › Email Notifications. - T+0secondsZoho Books
An invoice is created in Books
Verified liveThe invoice gets a normal
SFA/2026/…number, carries the sales order number as its reference, and has sales channelzstore. Books does not email this invoice; the store emails are the receipt.See itBooks (SwingFIT Academies FZ LLC) › Invoices. Reference starts withSO-. - T+0secondsZoho Flow
Books tells Zoho Flow, and four flows start
UnverifiedEach flow receives the invoice number and organization, looks the invoice up in Books, and does one job. All four sit in the Flow folder "Zoho POS/Commerce Flows" and were built by BiJoy.
- Loads the credits into GolfManagerVerified liveT+12s
Flow
Zoho POS/Commerce - GOLF MANAGERrunsUpdateCreditinGolfManager. It finds the customer in GolfManager by email (or creates them), adds a voucher with the right number of sessions and an expiry date, and marks the GolfManager sale as paid. Beginner lesson packs also get a matching practice-session voucher at AED 0. - Creates the Credits record in CRMVerified liveT+3m
Flow
ZOHOPOS/COMMERCE_ZOHOCRMrunsUpdateCreditsInCRM_FromPOS. It finds the CRM contact by email (or creates one) and adds one Credits record per pack: name, sessions, price, expiry. - Marks the contact as a ClientVerified live
Flow
Update Lifecycle Status_ClientrunsUpdateLifecycleStatus_Client. It sets Lifecycle Status toClientunless the person is already aMember. - Tells the team in CliqFrom code
Flow
SalePOS/Commerce Cliq Notificationposts service, price, customer and salesperson to#paygsaleswhen the price is above AED 250.
See itZoho Flow › folder "Zoho POS/Commerce Flows" › flow › History - T+3mafter creditsZoho CRM
CRM adds up the balances on the contact
Verified liveRule
GM Sync - Credits to Contact EngineA(Credits module) runssyncContactCredits. It totals each credit type onto the contact, for exampleRegular_Coaching_Credit_BalanceandPractice_Credit_Balance.See itCRM › contact › credit balance fields - T+3mafter creditsZoho CRM
First-time PAYG buyers get the welcome email
UnverifiedRule
sfaPaygonWelcomeruns the function of the same name. It sends the PAYG welcome ("Your golf lessons are ready.") from info@swingfitacademies.com to contacts who are aClientand have never had it, then marks themPaygon_Stage = 1. Members buying extra packs are skipped on purpose. The follow-up emails are in the PAYG nurture flow.See itCRM › contact › Emails tab
Emails and messages
CustomerOrder ConfirmedVerified liveYour order #Sales Order# is confirmed.
Full text (not found (Commerce native template, edited in-app 22 Sep; no export/HTML source file in the archive or AI OS folder — wording taken from the raw trace's live capture of the order))
CustomerOrder SummaryVerified liveOrder summary from Name.
Full text (not found (Commerce native template, same as above))
CustomerPAYG welcome (4 versions: coaching, practice, fitness, junior)UnverifiedYour golf lessons are ready.
Full text ($HOME/mnt/SwingFIT AI OS/crm_email_templates/flows/PAYGON-Copy-Station.html)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did they pay? | Books › Invoices (Studio City org) | Invoice Paid, reference SO-… |
| Can they book? | GolfManager › customer › Vouchers | New voucher created by "Swingfit CRM Api" with the right balance and end date |
| Does CRM know? | CRM › contact › Credits related list | New Credits record, same balance as GolfManager |
| Did they get the order emails? | Commerce › Orders › the order | Order Confirmed and Order Summary sent |
| Did they get the welcome? | CRM › contact › Emails tab | "Your golf lessons are ready." listed on the contact |
| Did the team hear about it? | Cliq › #paygsales | A "New Sale From POS/Commerce" post (sales over AED 250) |
| Did an automation fail? | Zoho Flow › the flow › History | Every run listed with success or error |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Store emails | Commerce › Settings › Customization › Email Notifications | The customer gets no order email |
| Each of the four flows | Zoho Flow › folder "Zoho POS/Commerce Flows" › toggle | That one job. The GolfManager flow is the critical one: without it the customer cannot book. |
| Balance roll-up, welcome email | CRM › Setup › Workflow Rules › module Credits | Contact balances go stale, or new PAYG buyers get no welcome |
Good to know
Customers are matched by email
GolfManager and CRM find the customer by the email used at checkout. A different email creates a new customer record in both.
Products need three fields in Books
Each item needs top-up credits, the GolfManager type ID and a duration on its Books item, or no credits are issued. Beginner packs are matched on exact names such as "4 x 60 min Beginner Golf Lesson".
Store sales are Studio City only
Zoho Commerce sits on the Studio City Books account. DIFC sales go through Zoho POS.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (6)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Zoho POS/Commerce - GOLF MANAGER469029000000020573 | flow | Active | Webhook fired when the Books invoice for the order is created Fires for every Commerce/POS invoice regardless of amount or item; branches inside the function by item name/custom fields | Calls function UpdateCreditinGolfManager(invoice_id, org_id), which re-fetches the invoice from Books, finds/creates the GolfManager customer by email, then POSTs to GolfManager's voucher recharge endpoint once per line item (amount/expiry/price read from the item's cf_top_up_credits, cf_golf_manager_type_id, cf_duration_months/cf_expiration custom fields), then marks the resulting GolfManager sale as paid via /api/billing/paySales. | Zoho Flow › folder "Zoho POS/Commerce Flows" (folder_id 469029000000046077), link_name zcommerce_creditpurchase $HOME/arch/flow_deluge_source/UpdateCreditinGolfManager.deluge |
ZOHOPOS/COMMERCE_ZOHOCRM469029000000062399 | flow | Active | Same Books-invoice-created webhook as the GolfManager flow Fires for every Commerce/POS invoice | Calls function UpdateCreditsInCRM_FromPOS(invoice_id, org_id). Finds the CRM Contact by the invoice's email, creating one (Last_Name/First_Name/Email/Phone) if none matches, then creates one Credits record per line item (Name, Balance, Expiry_Date, Player, Total_Price, Price_per_Credit) via a direct POST to crm/v2/Credits. | Zoho Flow › folder "Zoho POS/Commerce Flows", link_name zohopos_commerce_zohocrm $HOME/arch/flow_deluge_source/UpdateCreditsInCRM_FromPOS.deluge |
Update Lifecycle Status_Client469029000000112017 | flow | Active | Same Books-invoice-created webhook Fires for every Commerce/POS invoice | Calls function UpdateLifecycleStatus_Client(invoice_id, org_id). Looks up the Books customer's contact person, finds the CRM Contact by email, and sets Lifecycle_Status to "Client" unless it is already "Member". Has no create-Contact fallback: if the email matches nothing in CRM, it calls zoho.crm.getRecordById("Contacts","") with a blank id and takes no further action (already flagged in the raw trace). | Zoho Flow › folder "Zoho POS/Commerce Flows", link_name update_lifecycle_status $HOME/arch/flow_deluge_source/UpdateLifecycleStatus_Client.deluge |
SalePOS/Commerce Cliq Notification469029000000351038 | flow | Active | Same Books-invoice-created webhook Only posts to Cliq if a line item's rate is over AED 250 (evaluated per line item, not per invoice; on a multi-item invoice the loop overwrites service/rate on each pass so only the LAST item is ever checked/reported) | Calls function SalePOS_Cliq_Notification(invoice_id, org_id), which re-fetches the invoice and posts a hard-coded-format message to Cliq channel paygsales via zoho.cliq.postToChannel naming service, rate, customer email/name, salesperson and location. | Zoho Flow › folder "Zoho POS/Commerce Flows", link_name salepos_cliq_notification $HOME/arch/flow_deluge_source/SalePOS_Cliq_Notification.deluge |
GM Sync - Credits to Contact EngineA6296422000045075173 | workflow rule | Active last run 2026-10-12T06:06 | Credits module, create or edit Fires on every Credits create/edit | Calls function syncContactCredits(contactId). Re-sums ALL of that Player's non-expired, positive-balance Credits records by name-matched category (Junior / Coaching → Member Lesson, Member Credit, Regular / Practice & Play / Golf Fitness) and writes the totals + nearest expiry onto the Contact's balance fields (Regular_Coaching_Credit_Balance, Practice_Credit_Balance, Fitness_Credit_Balance, Junior_Credit_Balance, Member_Lesson_Credit_Balance, Member_Coaching_Credit_Balance, Credit_Balance, plus matching *_Expiry / Credit_Expiry_Date fields). | CRM › Setup › Automation › Workflow Rules › module Credits $HOME/arch/crm_deluge_source/synccontactcredits.deluge |
sfaPaygonWelcome6296422000046337525 | workflow rule | Active last run 2026-10-12T06:06 | Credits module, create Contact.Lifecycle_Status must be "Client" (members/other statuses skipped) and Contact.Paygon_Stage must be 0/blank (first purchase only); Contact must have a non-zero balance in one of Regular_Coaching_Credit_Balance / Practice_Credit_Balance / Fitness_Credit_Balance / Junior_Credit_Balance (checked in that order — the first non-zero one picks the pack type/template) | Calls function sfaPaygonWelcome(contactId), which sends the CRM email template via crm/v8/Contacts/{id}/actions/send_mail, then sets Paygon_Stage=1 and Paygon_First_Purchase_Date=today. | CRM › Setup › Automation › Workflow Rules › module Credits $HOME/arch/crm_deluge_source/sfapaygonwelcome.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Invoice items (Zoho Books) | cf_top_up_credits | Number of GolfManager/CRM credits one unit of this item is worth | Set manually on the Books Item; read by UpdateCreditinGolfManager and UpdateCreditsInCRM_FromPOS |
| Invoice items (Zoho Books) | cf_golf_manager_type_id | The GolfManager voucher type ID this item recharges | Set manually on the Books Item; read by UpdateCreditinGolfManager |
| Invoice items (Zoho Books) | cf_duration_months / cf_expiration | Days added to today for the credit/voucher expiry (SC uses cf_duration_months, DIFC uses cf_expiration — both actually store a day count despite the SC field's name) | Set manually on the Books Item |
| Contacts | Lifecycle_Status | Client / Member / etc; gates the PAYG welcome email and is what Update Lifecycle Status_Client writes | UpdateLifecycleStatus_Client (Flow); other lifecycle flows for Member/Churned |
| Contacts | Paygon_Stage | 0/blank=never welcomed, 1=Day-0 welcomed, 2=Day-3 sent, 3=Day-7 sent (see payg-nurture) | sfaPaygonWelcome sets 1; sfaPaygonSweep advances 1→2 and 2→3 |
| Contacts | Paygon_First_Purchase_Date | Date of the first PAYG purchase; anchors the Day-3/Day-7 sweep timing | sfaPaygonWelcome |
| Contacts | Regular_Coaching_Credit_Balance / Practice_Credit_Balance / Fitness_Credit_Balance / Junior_Credit_Balance / Credit_Balance / Credit_Expiry_Date | Roll-up totals across all of that Player's live Credits records, by category | syncContactCredits |
| Credits | Name, Balance, Expiry_Date, Player, Total_Price, Price_per_Credit | One record per line item purchased | UpdateCreditsInCRM_FromPOS (create only, direct POST to crm/v2/Credits, not zoho.crm.createRecord) |
IDs and references
| What | Value |
|---|---|
| Zoho Flow folder (Commerce/POS shared flows) | 469029000000046077 — "Zoho POS/Commerce Flows" |
| Books org, Studio City | 866469739 |
| Books org, DIFC | 872210045 (not used by Commerce; store is Studio City only) |
| Cliq channel | paygsales |
| GolfManager voucher recharge endpoint | https://eu.golfmanager.com/api/vouchers/recharge.json |
| GolfManager voucher type, 4x/8x/12x Beginner Golf Lesson (paid) | 168 / 178 / 179 |
| GolfManager voucher type, matching free practice-session voucher | 168 (same id reused for the free companion voucher on the 4x Beginner pack) |
All flows › Desk sale (POS)
When the desk sells something in Zoho POS (incl. practice passes)
A POS sale at the desk tops up GolfManager credits or a membership, mirrors matching credits into CRM, and can alert staff on Cliq.
- Starts when
- A staff member at the front desk closes a sale in Zoho POS (Studio City or DIFC), creating a paid invoice in Zoho Books with sales_channel = "zpos".
- Covers
- Covers a walk-in sale rung up in Zoho POS at Studio City or DIFC — a coaching package/top-up or a Practice Pass — from the POS invoice landing in Books through to GolfManager credits/memberships, CRM Credits/lifecycle, and staff Cliq alerts. Does not cover online Commerce checkout (same back-end functions, different front door) or Zoho Billing subscription sales (a separate flow that is the ONLY path that populates the CRM Practice_Passes module).
- Systems
- Zoho POS, Zoho Books, Zoho Flow, GolfManager, Zoho CRM, Cliq
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Sale closed at deskZoho POS
POS invoice lands in Zoho Books
Verified liveThe desk rings up the sale on the till app; Zoho POS writes a paid invoice straight into Zoho Books with
sales_channel:"zpos". Studio City invoice numbers run SCI### (e.g. SCI284-SCI288); DIFC's run DIFC0### for POS specifically (plain INV-000### numbers at DIFC are non-POS "direct_sales"). The invoice carries the buyer's email/phone (if the desk captured them), the salesperson, and line items.See itZoho Books > Sales > Invoices, filter Sales Channel = POS. - T+secondsWebhooks fireZoho Flow
The same Flow folder used by online Commerce fires for POS
From codeCreating the invoice fires webhooks into the "Zoho POS/Commerce Flows" folder — the identical folder and functions the online store uses. Four flows apply to every POS sale:
Zoho POS/Commerce - GOLF MANAGER->UpdateCreditinGolfManager,ZOHOPOS/COMMERCE_ZOHOCRM->UpdateCreditsInCRM_FromPOS,SalePOS/Commerce Cliq Notification->SalePOS_Cliq_Notification, andUpdate Lifecycle Status_Client->UpdateLifecycleStatus_Client. A fifth,PracticePass/POS - GolfManager-->PracticePassPOSUpdateExpiryDate_GM_MembershipID, only matters when a line item is one of the 4 Practice Pass SKUs.- Referral credit (if buyer was referred)From codeT+seconds
POS/Commerce - CRM/Referralfactoryalso fires and can award a referrer credit in GolfManager viaUpdateReferrerCreditsInGolfManageer; not verified live in this trace.
See itZoho Flow > Zoho POS/Commerce Flows folder; each flow's run history. - T+13sGolfManager credit/voucherGolfManager
Buyer is matched (or created) in GolfManager and a voucher is recharged
Verified liveUpdateCreditinGolfManagerre-fetches the invoice from Books, matches the GolfManager customer by the invoice's email (creating one if no match), then recharges a voucher per line item sized off that item'scf_top_up_credits/cf_golf_manager_type_idcustom fields. Verified live: an invoice for one "4 x 60 min Beginner Golf Lesson" package (AED1997) produced a matching GolfManager voucher sale 13 seconds later, correctly invoiced.See itGolfManager customer record > Vouchers/Sales tab. - T+3minCRM CreditsZoho CRM
CRM Contact is matched (or created) and a Credits record is added
Verified liveUpdateCreditsInCRM_FromPOSsearches Contacts by the invoice email; if none matches it creates a new Contact from the invoice's name/email/phone. It then writes oneCreditsrecord per line item (Name, Balance, Expiry_Date, Price_per_Credit, linked to the Player).See itContact record > Credits related list. - T+3minLifecycle stampZoho CRM
Contact's Lifecycle_Status is stamped "Client"
Verified liveUpdateLifecycleStatus_Clientlooks up the Books customer's contact person, finds the matching CRM Contact by email, and setsLifecycle_Statusto "Client" unless it is already "Member" (Members are left alone).See itContact record > Lifecycle_Status field. - T+secondsStaff Cliq alertCliq
A staff alert posts to #paygsales for big-ticket sales
From codeSalePOS_Cliq_Notificationre-fetches the invoice and, if the line item's rate is over AED 250, posts a message to the #paygsales Cliq channel naming the service, rate, customer, salesperson and location (Studio City/DIFC). AED 250-or-under sales are skipped on purpose.See itCliq > #paygsales channel. - T+13sPractice Pass only: GolfManager membershipGolfManager
A Practice Pass line item creates a GolfManager membership and tags the invoice
Verified liveWhen a line item is "Practice Pass 15/30 Days 60/90 Minutes",
PracticePassPOSUpdateExpiryDate_GM_MembershipIDre-reads the invoice from the POS/Zakya API, matches or creates the GolfManager customer by the invoice's email, creates asubscriptionCustomermembership of the matching type, then writescf_golfmanager_membership_idandcf_practice_pass_expiry_dateback onto the POS invoice in Books.See itPOS invoice > custom fields (GolfManager Membership ID, Practice Pass Expiry Date); GolfManager customer > Memberships tab. - at expiryPractice Pass expiryGolfManager
Pass goes inactive on its own at the end date
Verified liveGolfManager deactivates the membership itself once its
enddate passes (active flips to 0). A separate function,POS_Practice_Pass_Expiry_Scheduler, is designed to remove the membership at expiry, but is not currently in use.See itGolfManager > customer > Memberships > Active column.
Emails and messages
Team#paygsales Cliq alertUnverified(Cliq post, no subject line)
Full text ($HOME/arch/flow_deluge_source/SalePOS_Cliq_Notification.deluge (exact string in code))
CustomerPractice Pass ConfirmationUnverified(set by CRM email template, id 6296422000049047923)
CustomerPractice Pass Two Days OutUnverified(set by CRM email template)
CustomerPractice Pass UpsellUnverified(set by CRM email template)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did this POS sale actually create/top-up the GolfManager account? | GolfManager > search customer by the buyer's email > Vouchers or Memberships tab. | One voucher or subscriptionCustomer record per line item, dated within a few seconds of the sale, matching the item and amount on the invoice. |
| Did the CRM side pick it up? | CRM > Contacts > search by email > Credits related list and Lifecycle_Status field. | One Credits record per line item, and Lifecycle_Status = Client (or Member, untouched). |
| Did a Practice Pass sold at the desk land on the right client and start counting down? | POS invoice's custom fields (GolfManager Membership ID, Practice Pass Expiry Date) plus that GolfManager customer's Memberships tab. | The membership ID on the invoice matches an active subscriptionCustomer under the buyer's own GolfManager profile, not a stray/duplicate one. |
| Why didn't the customer get a Practice Pass confirmation/reminder email? | CRM > Practice_Passes module, search by Player. | A Practice_Passes record exists here for the sold pass, linked to the Player. |
| Was the #paygsales alert missed for a big sale? | Cliq #paygsales channel history, and the invoice's own line items. | Alert only fires when a single line item's rate is over AED 250 — a multi-item invoice under that per-item threshold won't alert even if the total is bigger. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| GolfManager voucher/membership creation from a POS sale | Zoho Flow > Zoho POS/Commerce Flows > disable Zoho POS/Commerce - GOLF MANAGER (credits) and/or PracticePass/POS - GolfManager- (passes) | The invoice still posts in Books, but nothing is added to the customer's GolfManager account. |
| CRM Credits + Contact creation from POS | Zoho Flow > disable ZOHOPOS/COMMERCE_ZOHOCRM | No Credits record and no new Contact get created in CRM from that sale. |
| Lifecycle stamping | Zoho Flow > disable Update Lifecycle Status_Client | Contact's Lifecycle_Status is left as-is after a POS sale. |
| #paygsales staff alert | Zoho Flow > disable SalePOS/Commerce Cliq Notification | No Cliq message for any POS sale, big or small. |
Good to know
POS and the online store share one back end
A POS sale and an online Commerce checkout run through the same Flow folder and the same functions (UpdateCreditinGolfManager, UpdateCreditsInCRM_FromPOS, etc.) — one code path serves both front doors.
The invoice number prefix isn't the reliable POS marker
Studio City POS invoices are numbered SCI###; DIFC's are DIFC0###. But the field that automation actually keys off is sales_channel:"zpos" on the Books invoice, not the number prefix — DIFC also has plain INV-000### numbers for non-POS sales.
Matching is entirely by email
Both the GolfManager side and the CRM side find (or create) the buyer purely by the email captured on the POS invoice. If the desk doesn't capture an email, or captures the wrong one, the sale still posts in Books but nothing reliably links to the right customer record on either side.
Beginner lesson packs also get a matching practice-session voucher
Beginner lesson packs also get a matching practice-session voucher at AED 0.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (10)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Zoho POS/Commerce - GOLF MANAGER469029000000020573 | flow | Active last run 2026-09-20T15:09 | Webhook fired when a Books invoice is created with sales_channel:"zpos" or from Commerce Fires for every POS/Commerce invoice; branches inside the function by item name/custom fields | Calls function UpdateCreditinGolfManager(invoice_id, org_id) — same function the online store uses. Re-fetches the invoice from Books, finds/creates the GolfManager customer by email, recharges a voucher per line item (amount/expiry/price from the item's cf_top_up_credits/cf_golf_manager_type_id/cf_duration_months or cf_expiration custom fields), then marks the resulting GolfManager sale paid. | Zoho Flow › folder "Zoho POS/Commerce Flows" (folder_id 469029000000046077), link_name zcommerce_creditpurchase $HOME/arch/flow_deluge_source/UpdateCreditinGolfManager.deluge |
ZOHOPOS/COMMERCE_ZOHOCRM469029000000062399 | flow | Active last run 2026-09-20T15:12 | Same POS/Commerce invoice-created webhook Fires for every POS/Commerce invoice | Calls function UpdateCreditsInCRM_FromPOS(invoice_id, org_id). Finds/creates the CRM Contact by invoice email, then POSTs one Credits record per line item directly to crm/v2/Credits. | Zoho Flow › folder "Zoho POS/Commerce Flows", link_name zohopos_commerce_zohocrm $HOME/arch/flow_deluge_source/UpdateCreditsInCRM_FromPOS.deluge |
Update Lifecycle Status_Client469029000000112017 | flow | Active | Same POS/Commerce invoice-created webhook Fires for every POS/Commerce invoice | Calls function UpdateLifecycleStatus_Client(invoice_id, org_id). Looks up the Books contact, finds the CRM Contact by email, sets Lifecycle_Status to "Client" unless already "Member". Has no create-Contact fallback: when no CRM Contact matches, it takes no further action. | Zoho Flow › folder "Zoho POS/Commerce Flows", link_name update_lifecycle_status $HOME/arch/flow_deluge_source/UpdateLifecycleStatus_Client.deluge |
SalePOS/Commerce Cliq Notification469029000000351038 | flow | Active | Same POS/Commerce invoice-created webhook Only alerts if a line item's rate > AED 250; the for-each loop overwrites service/rate on every pass, so a multi-item invoice is judged only on the LAST item, and the message only ever names that one item | Calls function SalePOS_Cliq_Notification(invoice_id, org_id), posting a fixed-format message to Cliq channel paygsales via zoho.cliq.postToChannel. | Zoho Flow › folder "Zoho POS/Commerce Flows", link_name salepos_cliq_notification $HOME/arch/flow_deluge_source/SalePOS_Cliq_Notification.deluge |
PracticePass/POS - GolfManager-469029000000353017 | flow | Active last run 2026-09-04T07:56 | Same POS/Commerce invoice-created webhook Only acts when a line item name is one of "Practice Pass 15/30 Days 60/90 Minutes" (exact string match) | Calls function PracticePassPOSUpdateExpiryDate_GM_MembershipID(invoiceID, OrgID). Re-reads the invoice from the Zakya/POS API, reads the item's cf_gm_membership_type_id (SC) or cf_gm_membership_type_id_1 (DIFC) custom field for the GolfManager membership type, finds/creates the GolfManager customer by the invoice email, creates a subscriptionCustomer membership of that type, then writes cf_golfmanager_membership_id and cf_practice_pass_expiry_date back onto the Books invoice. | Zoho Flow › folder "Zoho POS/Commerce Flows", link_name practicepass_pos_golfmanager $HOME/arch/flow_deluge_source/PracticePassPOSUpdateExpiryDate_GM_MembershipID.deluge |
POS/Commerce - CRM/Referralfactory469029000000257001 | flow | Active | Same POS/Commerce invoice-created webhook Only awards a credit if the buyer was referred (per Referral Factory linkage); not verified live in this trace | Calls function UpdateReferrerCreditsInGolfManageer, which can award a referrer credit voucher in GolfManager. | Zoho Flow › folder "Zoho POS/Commerce Flows", link_name pos_commerce_crm_referrer flow_functions.json id 469029000000257008 |
POS/ExpiryPracticePass - GolfManager469029000000353153 | flow | Inactive | Would fire on Practice Pass expiry (date-based) n/a — flow is disabled | Calls function POS_Practice_Pass_Expiry_Scheduler, which issues a hard DELETE on the GolfManager subscriptionCustomer record. Not currently in use; real passes expire on their own inside GolfManager (active flips to 0, record kept). | Zoho Flow › folder "Zoho POS/Commerce Flows", link_name pos_expirypracticepass_golfmanager $HOME/arch/flow_deluge_source/POS_Practice_Pass_Expiry_Scheduler.deluge |
Practice Pass Confirmation6296422000049084117 | workflow rule | Active last run 2026-07-30T08:59 | Practice_Passes, create Fires on any new Practice_Passes record; POS-desk sales don't currently create one (see fix_additions) | Calls function practicePassSendConfirmation, sending CRM email template 6296422000049047923. | CRM › Setup › Automation › Workflow Rules › module Practice_Passes crm_functions_live/functions/practicePassSendConfirmation.deluge |
Practice Pass Two Days Out6296422000049055176 | workflow rule | Active last run 2026-08-26T00:01 | Practice_Passes, date-based: End_Date - 2 days, once Status = active | Calls function practicePassSendTwoDaysOut. | CRM › Setup › Automation › Workflow Rules › module Practice_Passes crm_functions_live/functions/practicePassSendTwoDaysOut.deluge |
Practice Pass Upsell6296422000049109114 | workflow rule | Active last run 2026-07-30T09:07 | Practice_Passes, create Pass_Number >= 2 (2nd+ pass for the same Player) | Calls function practicePassSendUpsell. | CRM › Setup › Automation › Workflow Rules › module Practice_Passes crm_functions_live/functions/practicePassSendUpsell.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Books invoice | sales_channel | "zpos" identifies a POS sale (vs zstore for Commerce, direct_sales for Billing/other) — the field automation actually keys off, not the invoice number prefix | Zoho POS at invoice creation |
| Books invoice | cf_golfmanager_membership_id / cf_practice_pass_expiry_date | Links a Practice Pass POS invoice to its GolfManager membership record and stores its expiry | PracticePassPOSUpdateExpiryDate_GM_MembershipID |
| Books item | cf_gm_membership_type_id (SC) / cf_gm_membership_type_id_1 (DIFC) | GolfManager membership type id for a Practice Pass SKU | Set manually on the item |
| Contacts | Lifecycle_Status | Set to Client by a POS sale unless already Member | UpdateLifecycleStatus_Client |
| Credits | Name, Balance, Expiry_Date, Player, Total_Price, Price_per_Credit | One record per POS line item | UpdateCreditsInCRM_FromPOS |
| Practice_Passes | (whole module) | Only ever populated by the Zoho Billing subscription flow SubscriptionActivated_to_CRM — a POS-sold pass never creates a record here | SubscriptionActivated_to_CRM (Billing path, not POS) |
Full email text
Practice Pass Confirmation(set by CRM email template)
Practice Pass Two Days Out(set by CRM email template)
Practice Pass Upsell(set by CRM email template)
IDs and references
| What | Value |
|---|---|
| Zoho Flow folder | 469029000000046077 — "Zoho POS/Commerce Flows" |
| Books org, Studio City | 866469739 |
| Books org, DIFC | 872210045 |
| Cliq channel | paygsales |
| GolfManager voucher recharge endpoint | https://eu.golfmanager.com/api/vouchers/recharge.json |
| GolfManager billing pay-sales endpoint | https://eu.golfmanager.com/api/billing/paySales |
| Practice Pass POS webhook invoice source | api.zakya.com/inventory/v1/invoices (Zakya/POS API, not the standard Books v3 API used elsewhere) |
All flows › Membership signup
When someone signs up for a monthly membership
A new or returning member's monthly subscription activates GolfManager membership, CRM records, lesson credit, and a welcome email sequence.
- Starts when
- A monthly membership subscription goes live in Zoho Billing (Studio City or DIFC) after the customer pays online. There are two ways in: a staff member sends the customer a Billing payment link, or the customer finds the membership online and pays there. Memberships are not keyed in by staff at the desk.
- Covers
- Covers a prospect starting a recurring monthly membership subscription in Zoho Billing (Studio City org 866469739 or DIFC org 872210045) through to: GolfManager membership + first-month lesson credit, the CRM Memberships record, Contact Lifecycle_Status, the Books invoice, the F5/F5b onboarding email sequence, Billing's own subscription/invoice emails, the Zoho Creator commission-tracking mirror, the referral-factory credit, and the Deals-side 'Verify Won Billing' check. Does NOT cover: annual memberships, Practice Passes (separate branch of the same webhook), pause/resume/cancel, or PAYG single-session purchases.
- Systems
- Zoho Billing, Zoho Flow, Zoho CRM, GolfManager, Zoho Books, Meta Conversions API, Referral Factory
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Customer pays onlineZoho Billing
The customer pays online, which starts the subscription in Zoho Billing
Verified liveEvery membership is paid online. Either a staff member sends the customer a Zoho Billing payment link for the chosen plan (e.g.
SFMM2Membership PGA X2,SFPM997Practice & Play Membership), or the customer finds the membership online and pays there. Once payment goes through, the subscription is Live. Thesalesperson_nameon the subscription decides who owns the member in CRM later on.See itZoho Billing → Subscriptions → search by customer email. Status should be Live. - Same day (usually within the hour)Member tag added in GolfManagerGolfManager
The member tag is added in GolfManager
Verified liveBilling's activation webhook runs the
New_Resume_ReactivateMembershipZGOLFflow, which callsNew_Resume_Reactivate_SubToGM. It finds the customer in GolfManager (or creates them) and adds the member tag: a GolfManager membership of the type set on the Billing plan (for example "SwingFIT - Membership x2"), starting on the subscription start date. This is what lets the member do what members do: without the tag, GolfManager treats them as a non-member for booking and member rates. The GolfManager membership ID is written back to the Billing subscription (cf_golfmanager_membership_id). Practice Pass plans and non-membership items are skipped on purpose.See itGolfManager back office → Customers → the member → Memberships. Look for an active membership of the matching type (the member tag), starting on the subscription start date, created by "Swingfit CRM Api". - T+0 to T+1minReal-time CRM pushZoho Flow
The same webhook is meant to create the CRM Memberships record straight away
UnverifiedSubscriptionActivated_to_CRMis designed to re-fetch the subscription from Billing, look up the CRM Contact by email, route Practice Pass plan codes to thePractice_Passesmodule, and create/update everything else in theMembershipsmodule (Subscription_ID, Plan, Billing_Cycle, Amount, Start_Date, Next_Billing_Date, Member_Since, Owner mapped from salesperson, Billing_Org_ID). In practice the record lands through the nightly sync further down.See itn/a — internal webhook, no UI surface. - T+0 to T+1minInvoice-triggered credit + tracking pushesZoho Flow
The Books invoice for the sale fires two more automations
From codeThe same sale creates a Zoho Books invoice, which triggers: (1)
GMINVOICE_CRM_CREDITflow →UpdateMembershipCredits_CRM_SubscriptionInv— recharges the member's own first-month GolfManager lesson-credit voucher and logs a matchingCreditsrecord in CRM; (2)ZBilling - ReferralFactoryflow →GM_UpdateReferrerCredits— on a customer's *first* purchase only, converts any matching Lead into the existing Contact and, if the Contact carries a referrer, recharges the referrer's GM credit and qualifies them in Referral Factory.See itGolfManager → Customers → [name] → Vouchers/Credits tab; CRM → Credits related list on the Contact. - T+0 to T+1minMeta attribution pingZoho Flow
Purchase event sent to Meta, if the lead came from a Meta ad
From codeZSubscription - Meta(Zsubscription_to_meta) checks the Contact'sLead_Source; only if it equalsMeta_Adsdoes it hash the customer's email/phone and POST apurchaseevent to Meta's Conversions API with the plan value, for ad-attribution reporting. All other lead sources are intentionally skipped.See itMeta Events Manager → test events / recent activity, filtered by pixel 4473134646297796. - daily 02:00 Asia/DubaiNightly safety-net syncZoho CRM
Verified liveBilling Memberships Daily Syncschedule creates/updates the Memberships recordEvery night, the scheduled function
swingfit_sync_membershipsre-pulls each org's active/updated Billing subscriptions and creates or updates the CRMMembershipsmodule record, using the same field set as the initial push. This is the step that reliably lands the record — typically the calendar day after the subscription'sStart_Date.See itCRM → Setup → Automation → Schedules → 'Billing Memberships Daily Sync' → last run time/status. - T+0 to T+few hrs after the Memberships record existsOnboarding route decided, welcome email queuedZoho CRM
Gate function tags the record, then the matching E0 welcome email fires
UnverifiedF5_F5b_New_Member_Gateruns first on the Memberships record and setsOnboarding_Routeto one of 8 values (New vs Rejoin × Coaching vs Practice × Monthly vs Annual), based on how many prior Memberships the Player has and the plan name. A field-update workflow rule matching that exact route (e.g.Onboarding E0 - F5 New Coaching Monthly) then instant-sends the matching E0 welcome email.- Day 3 / 7 / 14 / 30 follow-upsVerified live
Four more workflow rules on the same route (E1–E4) fire as scheduled actions at Day 3, 7, 14 and 30 after the Memberships record's creation — not after the real signup date, since that's what the record's creation time is measured from.
See itCRM → Memberships record →Onboarding_Routefield; Contact → Emails related list. - daily 05:00 Asia/DubaiLifecycle status promoted to MemberZoho CRM
Verified liveLifecycleStatusSweeppromotes the Contact to a Member tiersfaLifecycleStatusSweepscans Contacts against their Memberships records and setsLifecycle_Statusto a member tier (e.g.Member) once a live Membership exists, roughly an hour after the nightly Memberships sync so the record is guaranteed to exist first.See itCRM → Contact →Lifecycle_Statusfield. - manual, whenever staff move the linked DealDeals-side sale verification (only if the Deal is worked)Zoho CRM
'Verify Won Billing' stamps the Deal as verified against Billing/Books — only fires if a Deal exists and is moved to Closed Won
From codeIf the prospect's journey included a Deal in the Sales Pipeline and a rep manually moves its Stage to 'Closed Won', the active workflow rule
Verify Won BillingrunssfaVerifyWonBilling: it checks the Player's Memberships for aliveone (or falls back to a paid Books invoice), tagsBilling_Verification/Books_Verification, and back-fillsAmountfrom a hardcoded plan-price table. This rule only fires when a rep manually advances the Deal to Closed Won.See itCRM → Deals → the Deal →Billing_Verification/Books_Verificationfields.
Emails and messages
CustomerF5 E0 — New Member welcomeVerified live"You're in, First Name Last Name"
CustomerF5 E1 — Day 3 nudgeVerified live"Have you booked your first lesson yet?"
CustomerF5b E0 — Rejoin welcomeVerified live"Good to have you back, Full Name"
CustomerF5/F5b E2/E3/E4 — Day 7 / 14 / 30 follow-upsUnverifiedNot confirmed live this session (not yet due for either example record)
CustomerT6 — Billing 'Subscription Activated' (custom, replaces Billing's default)UnverifiedNot captured this session
Full text (crm_email_templates/SFA-Billing-Placeholder-Reference.md)
CustomerBooks invoice email (T7 territory)Verified liveInvoice <number> from SwingFIT Academies (Books default subject pattern)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did the member actually get created as a paying subscription? | Zoho Billing → Subscriptions → search by email | Status = Live, correct plan and org |
| Does the member have their member tag in GolfManager? | GolfManager back office → Customer → Memberships/Subscriptions tab | An active membership of the matching type (the member tag), start date = subscription start date. Without it the member can't book or use member rates as a member. |
| Is it showing in CRM as a member? | CRM → Memberships module, search Subscription_ID; Contact → Lifecycle_Status | Memberships record Status = live, Billing_Org_ID populated; Contact Lifecycle_Status = Member (may take until the next day for both) |
| Did the welcome email go out? | Contact → Emails related list | An E0 welcome (F5 or F5b depending on new/rejoin) shows as sent, with an open event if the member opened it |
| Did the member get their first month's lesson credit in GolfManager? | GolfManager → Customer → Vouchers | A voucher of the matching lesson-credit type, dated same day as the invoice |
| Was a referral credited (if applicable)? | GolfManager → referrer's Customer → Vouchers; Referral Factory campaign 49133 dashboard | Only applies on the referred member's FIRST purchase; referrer's voucher recharge + qualified status |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| GolfManager member tag | Zoho Flow → 'New_Resume_ReactivateMembershipZGOLF' → disable | New and returning members would not get their member tag in GolfManager, so they could not book or use member rates as members until someone added it by hand. |
| CRM Memberships real-time push | Zoho Flow → 'Billing: Subscription Activated → CRM Membership Record' → disable | Only the nightly 02:00 batch (Billing Memberships Daily Sync) would still create the record. |
| Nightly Memberships batch | CRM → Setup → Automation → Schedules → 'Billing Memberships Daily Sync' → disable | New memberships stop appearing in CRM at all (given the real-time path isn't landing them either) — F5/F5b onboarding emails and Lifecycle_Status promotion would stop firing for new signups. |
| F5/F5b onboarding emails | CRM → Automation → Workflow Rules → the 24 'Onboarding E0–E4 - ...' rules, or just the gate function F5_F5b_New_Member_Gate | New/rejoining members get no automated welcome/nurture sequence. |
| Referral crediting on first purchase | Zoho Flow → 'ZBilling - ReferralFactory' → disable | No Lead-to-Contact conversion, no referrer GM credit recharge, no Referral Factory qualification on a customer's first purchase. |
| First-month GM lesson credit | Zoho Flow → 'GMINVOICE_CRM_CREDIT' → disable | New members get no lesson-credit voucher recharged in GolfManager off their invoice. |
Good to know
Practice Passes share the same webhook
SubscriptionActivated_to_CRM branches on plan code: PP15-60/PP15-90/PP30-60/PP30-90 go to the Practice_Passes module instead of Memberships, and never fall through to the membership logic.
Owner is assigned from the Billing salesperson
SubscriptionActivated_to_CRM maps the subscription's salesperson_name to a hardcoded list of CRM user IDs to set the Memberships record's Owner; anyone not on that list falls back to 'Member Success @ SFA'.
New vs Rejoin is decided by counting Membership records
The F5/F5b gate function counts a Player's total Memberships records (including cancelled ones) — 1 means new, more than 1 means rejoin (F5b), which is why a previously-cancelled member gets the 'Good to have you back' variant.
GolfManager side runs same-day; CRM side lands the next morning
The GolfManager member tag is added the same day the customer pays. The CRM Memberships record is created by the nightly batch early the next morning.
Deals module is not part of the working path
A member can go from Evaluation straight to a live paying membership without their Deal ever being moved to 'Closed Won' — the Deal simply sits at whatever stage it was left at. 'Verify Won Billing' only ever fires if/when a rep manually advances that Deal.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (32)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
New_Resume_ReactivateMembershipZGOLF469029000000020517 | flow | Active | Zoho Billing subscription-activation webhook none at flow level; plan-code skip logic is inside the function | Calls function New_Resume_Reactivate_SubToGM. | Zoho Flow > folder "Zoho Billing - Golf Manager" n/a (flow shell) |
New_Resume_Reactivate_SubToGM469029000000020677 | function | Active | called by flow New_Resume_ReactivateMembershipZGOLF validates org_id is 866469739 or 872210045; skips Practice Pass plan codes and non-membership items by design | Re-fetches the subscription from Zoho Billing, reads the plan's GolfManager membership-type custom field, finds-or-creates the GM customer, POSTs a GM subscriptionCustomer (the GM membership) starting on the subscription's start date, and writes the resulting GM membership id back onto the Billing subscription as cf_golfmanager_membership_id. Carries the GolfManager API key hardcoded in cleartext. The GolfManager membership it creates is the member's 'member tag' (GM subscription type from the Billing item's cf_gm_membership_type_id / _1 field, e.g. type 18 'SwingFIT - Membership x2'). Verified 2026-09-24 on subscriptionCustomer 1489 (created by user 'Swingfit CRM Api'). | Zoho Flow > folder "Zoho Billing - Golf Manager" > function flow_deluge_source/New_Resume_Reactivate_SubToGM.deluge (4,901 chars) |
Billing: Subscription Activated → CRM Membership Record469029000000307034 | flow | Active | Zoho Billing subscription-activation webhook none at flow level | Calls function SubscriptionActivated_to_CRM. Designed to create the CRM Memberships record in real time, but 8/8 recent live signups checked in the raw trace show the record actually lands via the nightly batch instead - see the nightly-sync automation below and its fix note. | Zoho Flow > folder "Zoho Billing - Zoho CRM/ Cliq" n/a (flow shell) |
SubscriptionActivated_to_CRM469029000000307044 | function | Active | called by flow Billing: Subscription Activated → CRM Membership Record branches on plan_code: PP15-60/PP15-90/PP30-60/PP30-90 route to Practice_Passes; everything else goes to Memberships | Re-fetches the subscription, looks up the CRM Contact by email, and upserts Subscription_ID, Plan, Billing_Cycle, Amount, Start_Date, Next_Billing_Date, Member_Since, Billing_Org_ID. Maps sub.salesperson_name against a hardcoded list of CRM user ids to set Owner, falling back to "Member Success @ SFA" (sp_name lookup, line ~212) if the salesperson isn't on that list. | Zoho Flow > folder "Zoho Billing - Zoho CRM/ Cliq" > function flow_deluge_source/SubscriptionActivated_to_CRM.deluge (9,431 chars, partially read) |
GMINVOICE_CRM_CREDIT469029000000062439 | flow | Active | Zoho Books invoice created (for the subscription sale) none at flow level | Calls function UpdateMembershipCredits_CRM_SubscriptionInv. | Zoho Flow > folder "Golf Manager - Zoho CRM/BOOKS" n/a (flow shell) |
UpdateMembershipCredits_CRM_SubscriptionInv469029000000062535 | function | Active | called by flow GMINVOICE_CRM_CREDIT n/a | Recharges the member's own first-month GolfManager lesson-credit voucher and logs a matching Credits record in CRM. | Zoho Flow > folder "Golf Manager - Zoho CRM/BOOKS" > function flow_deluge_source/UpdateMembershipCredits_CRM_SubscriptionInv.deluge (8,785 chars) |
ZBilling - ReferralFactory469029000000258001 | flow | Active | Zoho Billing invoice webhook internal: only on the customer's first purchase | Calls function GM_UpdateReferrerCredits (same function documented in traces/tech/referral.json, including its early-exit behavior for first-purchase customers with no referrer email). | Zoho Flow > folder "Zoho - Referral Factory" flow_deluge_source/GM_UpdateReferrerCredits.deluge (10,596 chars) - see traces/tech/referral.json for full detail |
ZSubscription - Meta469029000000229264 | flow | Active | Zoho Billing subscription-activation webhook Contact's Lead_Source equal "Meta_Ads" (checked inside the function; all other sources are intentionally skipped) | Calls function Zsubscription_to_meta, which hashes the customer's email/phone and POSTs a "purchase" event to the Meta Conversions API with the plan value, pixel 4473134646297796. | Zoho Flow > folder "Zoho - Meta" flow_deluge_source/Zsubscription_to_meta.deluge (3,595 chars) |
Billing Memberships Daily Sync6296422000045556008 | schedule | Active last run 2026-09-02T02:04 | daily 02:00 Asia/Dubai n/a | Runs function billing_memberships_daily_sync (the raw trace refers to it informally as "swingfit_sync_memberships" - the archived function's actual api_name is billing_memberships_daily_sync), which re-pulls each org's active/updated Billing subscriptions and upserts the CRM Memberships module using the same field set as the real-time push. Live evidence (8/8 recent signups) shows this nightly run, not the real-time flow, is what actually creates the record in practice. | CRM Setup > Automation > Schedules crm_deluge_source (function billing_memberships_daily_sync, 20,773 chars) |
RETIRED - Onboarding Route - superseded by sfaOnboardingRouteSweep6296422000045509037 | workflow rule | Inactive last run 2026-08-05T17:33 | Memberships create none | Deactivated 2026-08-05. Its function onboardingroute stamped Onboarding_Route on create, but a create-time write plus the 24 E0-E4 rules (originally create-triggered) raced unreliably - retired in favour of the schedule below. | CRM Setup > Automation > Workflow Rules > Memberships |
sfaonboardingroutesweep6296422000049885021 | schedule | Active last run 2026-09-01T15:05 | daily 15:00 (per schedules_live.tsv; the raw trace's "F5_F5b_New_Member_Gate" name does not match any archived function - this daily sweep is the actual live mechanism) goLive="2026-08-05" (no backfill on older memberships); skips fixture/test records by name | THIS IS NOW THE ONLY THING THAT STAMPS Onboarding_Route, per the function's own header comment. It exists because a field_update trigger (the 24 E0-E4 rules) does not fire when the field is written during a record's own creation - verified live 2026-08-05 (a same-second stamp via the nightly-sync path did not trigger E0; the same write via direct REST API did, in 3 seconds). Paginates all Memberships (up to 1,600 across 8 pages of 200), maps each record's Plan_Code against a hardcoded allow-list (SFPM, SFMM1-4, SFMM2Sen-4Sen) to a fixed route suffix - EVERY approved code maps to an "...Annual" suffix, since the comment states monthly-term membership options were retired from the approved catalog on 2026-08-07. Any other plan code is skipped and logged "NEEDS-REVIEW", not stamped. New-vs-Rejoin is decided by comparing the record's age against the Player's other Memberships records. Writes Onboarding_Route via zoho.crm.updateRecord with the 4th-argument option {"trigger":["workflow"]} - explicitly required, since the plain 3-argument form does not fire workflow rules on the same write (verified live: SUB-00188, stamped via the plain 3-argument form, did not trigger E0). | CRM Setup > Automation > Schedules crm_deluge_source/sfaonboardingroutesweep.deluge (8,864 chars, read in full) |
Onboarding E0 - F5 New Coaching Annual6296422000045535022 | workflow rule | Active last run 2026-09-19T15:03 | field_update on Onboarding_Route (Onboarding_Route equals "F5 New Coaching Annual"); instant action fires immediately on the field write Onboarding_Route equals "F5 New Coaching Annual" | Sends CRM email notification "F5 E0 New Coaching Annual" (id 6296422000045511135). Also fires WhatsApp template "Welcome" (id 6296422000047932007). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E0 - F5 New Practice Annual6296422000045514228 | workflow rule | Active last run 2026-08-08T15:03 | field_update on Onboarding_Route (Onboarding_Route equals "F5 New Practice Annual"); instant action fires immediately on the field write Onboarding_Route equals "F5 New Practice Annual" | Sends CRM email notification "F5 E0 New Practice Annual" (id 6296422000045511139). Also fires WhatsApp template "Welcome" (id 6296422000047932007). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E0 - F5b Rejoin Coaching Annual6296422000045512225 | workflow rule | Active last run 2026-09-29T15:04 | field_update on Onboarding_Route (Onboarding_Route equals "F5b Rejoin Coaching Annual"); instant action fires immediately on the field write Onboarding_Route equals "F5b Rejoin Coaching Annual" | Sends CRM email notification "F5b E0 Rejoin Coaching Annual" (id 6296422000045519055). Also fires WhatsApp template "Welcome" (id 6296422000047932007). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E0 - F5b Rejoin Practice Annual6296422000045525162 | workflow rule | Active last run 2026-08-29T15:03 | field_update on Onboarding_Route (Onboarding_Route equals "F5b Rejoin Practice Annual"); instant action fires immediately on the field write Onboarding_Route equals "F5b Rejoin Practice Annual" | Sends CRM email notification "F5b E0 Rejoin Practice Annual" (id 6296422000045533068). Also fires WhatsApp template "Welcome" (id 6296422000047932007). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E1 - F5 New Coaching6296422000045532113 | workflow rule | Active last run 2026-09-19T15:03 | field_update on Onboarding_Route (Onboarding_Route equals one of: "F5 New Coaching Annual", "F5 New Coaching Monthly"); scheduled action fires 3 day(s) after the Memberships record's own creation time Onboarding_Route equals one of: "F5 New Coaching Annual", "F5 New Coaching Monthly" | Sends CRM email notification "Onboarding E1 - F5 New Coaching" (id 6296422000045521123). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E1 - F5 New Practice6296422000045524121 | workflow rule | Active last run 2026-08-08T15:03 | field_update on Onboarding_Route (Onboarding_Route equals one of: "F5 New Practice Annual", "F5 New Practice Monthly"); scheduled action fires 3 day(s) after the Memberships record's own creation time Onboarding_Route equals one of: "F5 New Practice Annual", "F5 New Practice Monthly" | Sends CRM email notification "Onboarding E1 - F5 New Practice" (id 6296422000045526055). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E1 - F5b Rejoin Coaching6296422000045516060 | workflow rule | Active last run 2026-09-29T15:04 | field_update on Onboarding_Route (Onboarding_Route equals one of: "F5b Rejoin Coaching Annual", "F5b Rejoin Coaching Monthly"); scheduled action fires 3 day(s) after the Memberships record's own creation time Onboarding_Route equals one of: "F5b Rejoin Coaching Annual", "F5b Rejoin Coaching Monthly" | Sends CRM email notification "Onboarding E1 - F5b Rejoin Coaching" (id 6296422000045534069). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E1 - F5b Rejoin Practice6296422000045533072 | workflow rule | Active last run 2026-08-29T15:03 | field_update on Onboarding_Route (Onboarding_Route equals one of: "F5b Rejoin Practice Annual", "F5b Rejoin Practice Monthly"); scheduled action fires 3 day(s) after the Memberships record's own creation time Onboarding_Route equals one of: "F5b Rejoin Practice Annual", "F5b Rejoin Practice Monthly" | Sends CRM email notification "Onboarding E1 - F5b Rejoin Practice" (id 6296422000045524113). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E2 - F5 New6296422000045533090 | workflow rule | Active last run 2026-09-19T15:03 | field_update on Onboarding_Route (Onboarding_Route equals one of: "F5 New Coaching Annual", "F5 New Coaching Monthly", "F5 New Practice Annual", "F5 New Practice Monthly"); scheduled action fires 7 day(s) after the Memberships record's own creation time Onboarding_Route equals one of: "F5 New Coaching Annual", "F5 New Coaching Monthly", "F5 New Practice Annual", "F5 New Practice Monthly" | Sends CRM email notification "Onboarding E2 - F5 New" (id 6296422000045516056). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E2 - F5b Rejoin6296422000045516078 | workflow rule | Active last run 2026-09-29T15:04 | field_update on Onboarding_Route (Onboarding_Route equals one of: "F5b Rejoin Coaching Annual", "F5b Rejoin Coaching Monthly", "F5b Rejoin Practice Annual", "F5b Rejoin Practice Monthly"); scheduled action fires 7 day(s) after the Memberships record's own creation time Onboarding_Route equals one of: "F5b Rejoin Coaching Annual", "F5b Rejoin Coaching Monthly", "F5b Rejoin Practice Annual", "F5b Rejoin Practice Monthly" | Sends CRM email notification "Onboarding E2 - F5b Rejoin" (id 6296422000045519059). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E3 - F5 New6296422000045527152 | workflow rule | Active last run 2026-09-19T15:03 | field_update on Onboarding_Route (Onboarding_Route equals one of: "F5 New Coaching Annual", "F5 New Coaching Monthly", "F5 New Practice Annual", "F5 New Practice Monthly"); scheduled action fires 14 day(s) after the Memberships record's own creation time Onboarding_Route equals one of: "F5 New Coaching Annual", "F5 New Coaching Monthly", "F5 New Practice Annual", "F5 New Practice Monthly" | Sends CRM email notification "Onboarding E3 - F5 New" (id 6296422000045524117). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E3 - F5b Rejoin6296422000045532131 | workflow rule | Active last run 2026-09-29T15:04 | field_update on Onboarding_Route (Onboarding_Route equals one of: "F5b Rejoin Coaching Annual", "F5b Rejoin Coaching Monthly", "F5b Rejoin Practice Annual", "F5b Rejoin Practice Monthly"); scheduled action fires 14 day(s) after the Memberships record's own creation time Onboarding_Route equals one of: "F5b Rejoin Coaching Annual", "F5b Rejoin Coaching Monthly", "F5b Rejoin Practice Annual", "F5b Rejoin Practice Monthly" | Sends CRM email notification "Onboarding E3 - F5b Rejoin" (id 6296422000045528037). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E4 - F5 New Coaching Annual6296422000045520068 | workflow rule | Active last run 2026-09-19T15:03 | field_update on Onboarding_Route (Onboarding_Route equals "F5 New Coaching Annual"); scheduled action fires 30 day(s) after the Memberships record's own creation time Onboarding_Route equals "F5 New Coaching Annual" | Sends CRM email notification "Onboarding E4 - F5 New Coaching Annual" (id 6296422000045512233). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E4 - F5 New Practice Annual6296422000045535034 | workflow rule | Active last run 2026-08-08T15:03 | field_update on Onboarding_Route (Onboarding_Route equals "F5 New Practice Annual"); scheduled action fires 30 day(s) after the Memberships record's own creation time Onboarding_Route equals "F5 New Practice Annual" | Sends CRM email notification "Onboarding E4 - F5 New Practice Annual" (id 6296422000045511151). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E4 - F5b Rejoin Coaching Annual6296422000045523060 | workflow rule | Active last run 2026-09-29T15:04 | field_update on Onboarding_Route (Onboarding_Route equals "F5b Rejoin Coaching Annual"); scheduled action fires 30 day(s) after the Memberships record's own creation time Onboarding_Route equals "F5b Rejoin Coaching Annual" | Sends CRM email notification "Onboarding E4 - F5b Rejoin Coaching Annual" (id 6296422000045521127). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Onboarding E4 - F5b Rejoin Practice Annual6296422000045522086 | workflow rule | Active last run 2026-08-29T15:03 | field_update on Onboarding_Route (Onboarding_Route equals "F5b Rejoin Practice Annual"); scheduled action fires 30 day(s) after the Memberships record's own creation time Onboarding_Route equals "F5b Rejoin Practice Annual" | Sends CRM email notification "Onboarding E4 - F5b Rejoin Practice Annual" (id 6296422000045514236). | CRM Setup > Automation > Workflow Rules > Memberships n/a (CRM workflow rule, no Deluge function - template in crm_email_templates/F5-F5b-Upload-Station.html; see crm_email_templates/SFA-F5-F5b-MEMBER-ONBOARDING-DEPLOY-KIT.md) |
Stamp Onboarding Start6296422000046223158 (rule) / stamp_onboarding_start function | function | Active | Memberships create none | Small (473-char) function stamping an onboarding-start marker field on the new Memberships record. | CRM Setup > Automation > Workflow Rules > Memberships crm_deluge_source/stamp_onboarding_start.deluge |
LifecycleStatusSweep6296422000050282009 | schedule | Active last run 2026-09-02T05:03 | daily 05:00 Asia/Dubai n/a | Runs function lifecyclestatussweep, which scans Contacts against their Memberships records and sets Lifecycle_Status to a member tier (e.g. "Member") once a live Membership exists - timed roughly an hour after the 02:00 nightly Memberships sync so the record is guaranteed to exist first. | CRM Setup > Automation > Schedules crm_deluge_source (function lifecyclestatussweep, 13,147 chars) |
Verify Won Billing6296422000052141060 | workflow rule | Active last run 2026-08-31T17:52 | field_update (Deal Stage moved to Closed Won) n/a beyond the field_update trigger | Runs function sfaVerifyWonBilling, which checks the Player's Memberships for a live one (or falls back to a paid Books invoice), tags Billing_Verification (default "Unverified - Needs Review") and Books_Verification, and back-fills Amount from a hardcoded plan-price table (997/1297/1497/1697/1897/2097/5997) rather than the actual invoice total unless no tier matches, in which case it falls back to invTotal. | CRM Setup > Automation > Workflow Rules > Deals crm_deluge_source/sfaverifywonbilling.deluge (4,596 chars, read in full) |
NewSubscriptionZGOLF (dead)469029000000020325 | flow | Inactive/disabled | n/a - disabled n/a | Earlier version of the GM membership-creation logic (function NewSubscription_GM), fully superseded by New_Resume_Reactivate_SubToGM. | Zoho Flow > folder "Zoho Billing - Golf Manager" flow_deluge_source/NewSubscription_GM.deluge (4,935 chars) - kept in archive, not deleted from Zoho Flow yet |
Billing: New Subscription → CRM Membership Record (dead)469029000000307001 | flow | Inactive/disabled | n/a - disabled draft n/a | June-2026 draft superseded by the live "Billing: Subscription Activated → CRM Membership Record". | Zoho Flow > folder "Zoho Billing - Zoho CRM/ Cliq" n/a |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Memberships | Subscription_ID / Plan / Billing_Cycle / Amount / Start_Date / Next_Billing_Date / Member_Since / Billing_Org_ID | Core membership record fields mirrored from Zoho Billing | SubscriptionActivated_to_CRM (designed real-time path); billing_memberships_daily_sync (the path that actually lands it) |
| Memberships | Owner | Mapped from the Billing subscription's salesperson_name against a hardcoded CRM-user list; falls back to "Member Success @ SFA" if unmatched | SubscriptionActivated_to_CRM |
| Memberships | Onboarding_Route | One of the F5/F5b x Coaching/Practice x Monthly/Annual route values that gates which welcome-email rule fires | sfaonboardingroutesweep (daily 15:00 schedule) - not the create-time gate the raw trace implies |
| Practice_Passes | (whole module) | Practice Pass plan codes (PP15-60/PP15-90/PP30-60/PP30-90) branch here instead of Memberships | SubscriptionActivated_to_CRM |
| Contacts | Lifecycle_Status | Promoted to a member tier once a live Membership exists | lifecyclestatussweep (daily 05:00 schedule) |
| Deals | Billing_Verification / Books_Verification / Amount | Verification stamp + back-filled sale amount, only written if a rep manually moves the Deal to Closed Won | sfaVerifyWonBilling |
| Zoho Billing subscription | cf_golfmanager_membership_id | The resulting GolfManager membership id, written back onto the Billing subscription | New_Resume_Reactivate_SubToGM |
Full email text
F5 E0 - New Member welcomeYou're in, First Name Last Name
F5 E1 - Day 3 nudgeHave you booked your first lesson yet?
F5b E0 - Rejoin welcomeGood to have you back, Full Name
SFA F5 New Coaching Annual E0You're in, Memberships.Player
SFA F5 New Practice Annual E0You're in, Memberships.Player
SFA F5b Rejoin Coaching Annual E0Good to have you back, Memberships.Player
SFA F5b Rejoin Practice Annual E0Good to have you back, Memberships.Player
SFA F5 New Coaching E1Have you booked your first lesson yet?
SFA F5 New Practice E1Have you booked your first session yet?
SFA F5b Rejoin Coaching E1Have you booked your first lesson back?
SFA F5b Rejoin Practice E1Have you booked your first session back?
SFA F5 New Member E2One week in — how's it going?
SFA F5b Rejoin E2One week back — how's it feeling?
SFA F5 New Member E3Two weeks in — what the best members do
SFA F5b Rejoin E3Two weeks back — you're in your stride
SFA F5 New Coaching Annual E4Month 1 done — make month 2 count
SFA F5 New Practice Annual E4Month 1 done — make month 2 count
SFA F5b Rejoin Coaching Annual E4Month 1 back — make month 2 count
SFA F5b Rejoin Practice Annual E4Month 1 back — make month 2 count
IDs and references
| What | Value |
|---|---|
| Zoho Billing org - Studio City | 866469739 |
| Zoho Billing org - DIFC | 872210045 |
| Meta pixel | 4473134646297796 |
| Zoho Creator app - commission tracking | golf-manager (All_Memberships / Membership_Renewal) |
| Plan codes routed to Memberships (approved, current catalog) | SFPM, SFMM1, SFMM2, SFMM3, SFMM4, SFMM2Sen, SFMM3Sen, SFMM4Sen - all mapped to an Annual route suffix |
| Plan codes routed to Practice_Passes | PP15-60, PP15-90, PP30-60, PP30-90 |
| sfaVerifyWonBilling hardcoded plan-price tiers | 997 / 1297 / 1497 / 1697 / 1897 / 2097 / 5997 |
All flows › Lesson booking
When a lesson is booked, reminded, cancelled or rescheduled
GolfManager bookings sync into CRM, which sends confirmation, reminder and cancellation emails and feeds a staff rebooking digest.
- Starts when
- A booking is created, edited, cancelled or rescheduled in GolfManager (production, tenant swingfit) — by a customer online, by a coach in GM, or by staff at the front desk.
- Covers
- Covers a member or PAYG client booking, cancelling or rescheduling a coached lesson, evaluation, or self-serve bay/practice slot in GolfManager, and everything that fires in Zoho CRM as a result: the CRM Bookings record, the credit/voucher deduction, the confirmation/reminder/nurture emails, and the staff rebooking digest. Does NOT cover the initial evaluation-booking write path (separate trace), membership billing, or POS/Books invoicing.
- Systems
- Zoho CRM, GolfManager, Zoho Flow
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Booking saved in GMGolfManager
Booking is created or edited in GolfManager
Verified liveA booking (coached lesson, evaluation, or bay/practice slot) is created, edited, cancelled or rescheduled directly in GolfManager. GM fires a webhook to Zoho Flow for create/update events. GolfManager does not send its own confirmation, reminder or after-session emails for this flow — Zoho CRM is the source for all customer-facing booking emails.
See itGolfManager booking record, fields confirmationSent/reminderSent/afterMailSent. - T+1s to T+2sWebhook → Zoho FlowZoho Flow
GolfManager webhook creates/updates the CRM Bookings record
Verified liveFlow
GM_ZCRM_BookingCreateUpdatereceives the webhook and calls its custom functionGM_ZCRM_BookingCreate_Upsert. That function looks up the GM customer by email, finds or creates the matching CRM Contact (converting a Lead if needed), and upserts aBookingsrecord keyed on the GM booking id (Name= GM booking id), setting Start/End time, Price, Resource_Name and Booking_Details. Cancellations are handled by a separate flow,GM_ZCRM_BookingCancelled.- Live exampleVerified liveT+1s
Lesson GM id 198939 (Coach Brad, SC): GM created 2026-09-23T08:00:58+04. CRM Bookings record created 2026-09-23T08:00:59+04 — 1 second later.
- Live example — cancellationVerified liveT+2s
Bay booking GM id 198942 (Bay 4 SC): GM cancellation 2026-09-23T08:37:53+04. CRM Bookings.Status flipped to Cancelled, Modified_Time 2026-09-23T08:37:55+04 — 2 seconds later.
See itZoho Flow → gmbookings_zohocrm → Task History. - T+0 (on Bookings create)Booking ID stampZoho CRM
CRM stamps a friendly booking reference
From codeWorkflow rule
Bookings Info UpdatefiresbookingIDon every Bookings create to finish setting up the record for the rest of the automation to key off.See itCRM Setup → Automation → Workflow Rules → Bookings Info Update. - T+0 (on Bookings create/edit, repeating)Contact roll-up syncZoho CRM
Booking is rolled up onto the Contact record
Verified liveWorkflow rule
GM Sync - Bookings to Contact EngineAfiressyncContactBookingson every Bookings create or edit, keeping the Contact's Next_Booking_Ref / Next_Session_Date / Next_Session_Coach / Last_Booking_Date fields current. This is the field staff and other automations (rebooking digest, coach digest) read instead of querying Bookings directly.See itContact record — Next_Booking_Ref, Next_Session_Date, Next_Session_Coach. - T+0 (on Bookings create)Confirmation emailZoho CRM
Booking confirmation email fires
UnverifiedWorkflow rule
Booking ConfirmationfiressfaConfirmon every Bookings create, no criteria. The function branches by Resource_Name: Bay bookings get template F6E1, coach bookings get F7E1 (or F7ME1 for members), and sends via the Bookings/actions/send_mailAPI.See itContact → Emails related list. - T-2 days48h get-ready reminderZoho CRM
48-hour reminder for coached lessons
From codeDate-based workflow rule
Lesson 48h Get-ReadyfiressfaReminder482 days before Start_Date_and_Time. Only sends for coach bookings (Resource_Name contains "Coach", excludes "Evaluation") — bay bookings and evaluations are skipped by the function's own logic.See itBookings record → Email_Sent field should contain F7E3/F7ME3. - T-1 dayDay-before reminderZoho CRM
Day-before reminder for coached lessons
From codeDate-based workflow rule
Lesson Day-BeforefiressfaReminderDayBefore1 day before Start_Date_and_Time, same coach-only branch logic as the 48h reminder.See itBookings record → Email_Sent field should contain F7E2/F7ME2. - T-1 dayPre-lesson expectations reminderZoho CRM
Pre-lesson expectations reminder (separate from the day-before reminder)
UnverifiedDate-based rule
P3 Pre-Lesson Expectations Reminderis designed to firesfa3prelesson1 day before Start_Date_and_Time, sending a separate expectations message ahead of the lesson.See itCRM Setup → Automation → Workflow Rules (search "P3"). - T+2h after End_Date_and_TimePost-session follow-upZoho CRM
Post-session follow-up email
UnverifiedDate-based rule
Post-Session Follow-upis designed to firesfaPostSession2 hours after the lesson ends, branching by Booking_Details for eval-specific copy or by Resource_Name for bay/coach nurture, capped to once per 60 days for nurture sends.See itCRM Setup → Automation → Workflow Rules (search "Post-Session"). - T+3 days after End_Date_and_Time3-day nurtureZoho CRM
3-day nurture email
UnverifiedDate-based rule
3 Days Nurtureis designed to firesfaDay3, sending to evaluation/intro bookings (via Booking_Details) or a capped bay nurture for non-members.See itCRM Setup → Automation → Workflow Rules (search "3 Days Nurture"). - T+7 days after End_Date_and_Time7-day nurtureZoho CRM
7-day nurture email
UnverifiedDate-based rule
7 Days Nurtureis designed to firesfaDay7, sending to evaluation/intro bookings only.See itCRM Setup → Automation → Workflow Rules (search "7 Days Nurture"). - T+0 (on Status → Cancelled)Cancellation emailZoho CRM
Cancellation email + accounting
Verified liveField-update rule
SFAbookingcancelledfiressfaBookingCancelledwhenever Bookings.Status becomes "Cancelled", sending template T5 and guarding against double-send with a staff-cancel flag (T3).See itContact → Emails related list; Bookings.Email_Sent should contain T5. - T+0 (on Start_Date_and_Time change)Reschedule emailZoho CRM
Reschedule confirmation email
UnverifiedField-update rule
SFAbookingRescheduledfiressfabookingreschedulewhenever Start_Date_and_Time changes on an existing booking. Guarded by a Last_Reschedule_Sent cooldown (min 1 day between sends) and skipped if the booking is Cancelled.See itContact → Emails related list; Bookings.Last_Reschedule_Sent. - T+0 (on Bookings create)Same-day pingZoho CRM
Same-day booking staff ping
From codeWorkflow rule
sfaSameDayBookingPingfires on every Bookings create — an internal staff notification for bookings made for the same day.See itCRM Setup → Automation → Workflow Rules (search "SameDay"). - On voucher/credit-funded bookingCredit deductionZoho Flow
Credit/voucher balance is designed to be deducted in CRM when a booking consumes one
UnverifiedFlow
Voucher Consumed in GMis designed to callUpdateCRMCredits_VoucherConsumption, which looks up the GM customer's email, finds the matching CRM Contact, matches an Active Credit record by name, and reduces its Balance by the consumed units.See itZoho Flow → voucher_consumed_in_gm. - Daily ~15:30 Asia/DubaiRebooking digestZoho CRM
Staff digest of coaching clients who haven't rebooked
Verified liveSchedule
sfabookingsweep(internal namesfaRebookingDigest) runs daily and scans today's completed coach bookings (Resource_Name starts with "Coach", excludes Evaluation/Cancelled, ended >30 min ago). For each, it checks whether the customer already has a future lesson or practice booking on the calendar, and for member-tier contacts whether they've used their practice access. It stamps Rebook_Lesson_Booked / Rebook_Practice_Booked / Stamped_Coach / Rebook_Alert_Time on the Bookings record and emails an HTML digest grouped by location and category to Max and Akash only — confirmed intentional, not the wider team.See itDaily email to max@ and akash@swingfitacademies.com; Bookings record Rebook_* fields.
Emails and messages
CustomerBooking Confirmation (Bay)Unverified(template F6E1 — bay booking confirmation)
CustomerBooking Confirmation (Coach)Unverified(template F7E1/F7ME1 — coached lesson confirmation)
CustomerLesson 48h Get-ReadyUnverified(template F7E3/F7ME3)
CustomerLesson Day-Before ReminderUnverified(template F7E2/F7ME2)
Full text (crm_email_templates/flows_bookings/Flow-7-PAYG-Lesson-Reminder_E2.html)
CustomerP3 Pre-Lesson Expectations ReminderUnverified(pre-lesson expectations copy)
CustomerPost-Session Follow-upUnverified(varies by booking type)
Full text (crm_email_templates/flows_bookings/Flow-7-PAYG-Lesson-Followup_E4.html (currently inactive rule))
Customer3 Days NurtureUnverified(varies — eval/intro nurture)
Customer7 Days NurtureUnverified(varies — eval/intro nurture)
CustomerBooking Cancellation (T5)Unverified(template T5 — booking cancellation)
Full text (crm_email_templates/flows/T5_Booking-Cancellation.html)
CustomerBooking Reschedule ConfirmationUnverified(reschedule confirmation)
Full text (crm_email_templates/flows_bookings/Flow-Booking-Reschedule-Confirmation.html (a real template copy DOES exist, contrary to the raw trace's note that no code-home copy exists for the function itself - the function code sfabookingreschedule.deluge is the orphan, not the email template))
TeamRebooking DigestVerified live(HTML digest grouped by location/category)
Full text (crm_email_templates/flows_bookings/REBOOK-6-weekly-digest.html - NOTE: this file describes a weekly summary format, but sfabookingsweep's own description and the raw trace both say the actual daily digest is built inline in the function with no separate template file; this HTML may be an alternate draft that does not match what is actually sent.)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did the customer get their booking confirmation? | CRM Contact → Emails related list, or Bookings record → Email_Sent field (should contain a code like F6E1/F7E1/F7ME1) | An entry with subject matching the template and a recent sent_time; Email_Sent field carries the code |
| Is a booking missing from the CRM entirely? | COQL: Bookings where Name = '<GM booking id>' — compare against GolfManager get_record for the same id | A CRM Bookings row exists with matching Start/End/Resource_Name/Customer |
| Why does a booking show no coach (Resource_Name blank)? | Compare Bookings.Resource_Name against GolfManager's own resourceName field for the same booking id. | Resource_Name matches GolfManager's resourceName exactly |
| Is the credit/voucher balance updating when a member books with a credit? | CRM Credits related list on the Contact vs GolfManager customer voucher balance | Balances match between CRM and GolfManager |
| Did today's rebooking digest go out? | max@swingfitacademies.com / akash@swingfitacademies.com inbox, daily ~15:30 | One HTML digest email received, grouped by location |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| All booking-triggered CRM emails for this flow | CRM Setup → Automation → Workflow Rules → toggle off Booking Confirmation, Lesson 48h Get-Ready, Lesson Day-Before, SFAbookingcancelled, SFAbookingRescheduled (the currently-active ones) | Customers stop receiving any booking-related email; the CRM Bookings record still gets created/updated |
| CRM Bookings record creation itself | Zoho Flow → disable gmbookings_zohocrm (GM_ZCRM_BookingCreateUpdate) and gm_zcrm_bookingcancelled | No new CRM Bookings records at all — GolfManager keeps working, CRM stops mirroring it, and every downstream step in this trace stops firing |
| Contact roll-up fields (Next_Booking_Ref etc.) | CRM Setup → Automation → Workflow Rules → GM Sync - Bookings to Contact EngineA | Contact record stops showing next-session info; rebooking digest and coach digest lose their data source |
| Staff rebooking digest | CRM Setup → Automation → Schedules → sfabookingsweep | Max and Akash stop getting the daily rebooking digest email |
Good to know
GolfManager does not send its own booking emails
confirmationSent/reminderSent/afterMailSent read false on a live booking — GM relies entirely on CRM for customer-facing booking emails in this flow.
Coach vs bay branching is driven by Resource_Name text
Every function branches on whether Resource_Name starts with "Bay" or contains "Coach" (excluding "Evaluation"). This is why a trustworthy Resource_Name matters across the whole flow, not just for staff visibility.
Cancellations are a separate Flow from creates/updates
GM_ZCRM_BookingCancelled is a distinct, separately-maintained Zoho Flow from GM_ZCRM_BookingCreateUpdate — a fix to one does not touch the other.
Email_Sent field prevents duplicate sends
Every customer-facing booking email function checks and stamps a short code (e.g. F6E1, T5) on Bookings.Email_Sent before sending, so re-running a step manually on an already-sent booking is a no-op by design.
Rebooking digest recipients are deliberately narrow
Max confirmed (2026-07-31) that Max+Akash-only is correct for the rebooking digest — it is an internal staff tool, not a customer or wider-team communication.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (21)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
GM_ZCRM_BookingCreateUpdate469029000000062293 (link gmbookings_zohocrm) | flow | Active last run 2026-09-23T08:00 | GolfManager webhook on booking create/update none (all booking types) | Calls custom function GM_ZCRM_BookingCreate_Upsert: looks up/creates the CRM Contact by GM customer email, then upserts a Bookings record keyed on GM booking id (Name field), writing Start/End time, Price, Resource_Name, Booking_Details. | Zoho Flow > folder Golf Manager - Zoho CRM/BOOKS arch/raw_capture/flow_functions.json (function GM_ZCRM_BookingCreate_Upsert); flow_deluge_source |
GM_ZCRM_BookingCreate_Upsertn/a (Flow custom function) | function | Live last run see flow above | called by the flow above n/a | Contact lookup/create + Lead conversion if needed, then Bookings upsert by GolfManager booking id. | Zoho Flow custom function attached to GM_ZCRM_BookingCreateUpdate arch/flow_deluge_source (GM_ZCRM_BookingCreate_Upsert) |
GM_ZCRM_BookingCancelled469029000000156021 (link gm_zcrm_bookingcancelled) | flow | Active last run 2026-09-23T08:37 | GolfManager webhook on booking cancellation none | Sets the matching CRM Bookings.Status to Cancelled. Does not touch Noshow_Flag. | Zoho Flow > folder Golf Manager - Zoho CRM/BOOKS arch/flow_deluge_source |
Bookings Info Update6296422000045211188 | workflow rule | Active last run 2026-10-12T06:20 | Bookings create none | Calls function bookingID which stamps a friendly booking reference and other setup fields for the rest of the automation chain to key off. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/bookingid.deluge |
sfaBookingAttributionStamp6296422000048462102 | workflow rule | Active last run 2026-10-12T06:20 | Bookings create none (unconditional) | Runs function sfaBookingAttributionStamp, which reads the booking's linked Player (Contact) and copies over any UTM_Source/Medium/Campaign/Content/Term, UTM_ID, GA_Client_ID, FBCLID and Self_Reported_Source values the Player already has onto the booking, plus the Player's Google_GCLID into the booking's GCLID field - only filling fields that are currently blank on the booking, never overwriting an existing value. | CRM Setup > Automation > Workflow Rules > Bookings crm_deluge_source/sfabookingattributionstamp.deluge (read in full) |
Update Booking End Date in player-Last Activity Date6296422000040112013 | workflow rule | Active last run 2026-10-12T06:20 | Bookings create none (unconditional) | Runs function updatelastactivitydate (473 chars), which stamps the booking's End_Date_and_Time onto the linked Player's Last_Activity_Date field, so a Contact's most recent booking always reflects when they were last on the calendar. | CRM Setup > Automation > Workflow Rules > Bookings crm_deluge_source (function updatelastactivitydate, 473 chars) |
Jan 2026 Update Coach in Players6296422000029387120 | workflow rule | Active last run 2026-10-11T19:59 | Bookings create or edit 9 sequenced branches, each matching the booking's Resource_Name against a specific coach's named resource slots (e.g. "Coach Brad (SC)"/"Coach Brad (Evaluations SC)", "Head Coach Richard (SC)"/"(DIFC)"/"(Evaluations SC)"/"Evaluations Richard (DIFC)", similarly for Greg, Pradeep, Stian, Fraser, and the 3 Fitness-coach resource names) | Instant field-update actions (no custom function) that set the linked Contact's Coach lookup field to the matching coach whenever a booking's Resource_Name matches one of the hardcoded resource-name strings for that coach. Oldest rule in this flow (built January 2026); still active and firing on every booking create/edit. | CRM Setup > Automation > Workflow Rules > Bookings n/a (CRM instant field-update actions, no Deluge function) |
GM Sync - Bookings to Contact EngineA6296422000045075165 | workflow rule | Active last run 2026-10-12T06:20 | Bookings create or edit (repeatable) none | Calls function syncContactBookings, which keeps the Contact's Next_Booking_Ref / Next_Session_Date / Next_Session_Coach / Last_Booking_Date fields current from the latest Bookings record. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/synccontactbookings.deluge |
Booking Confirmation6296422000045328003 | workflow rule | Active last run 2026-10-12T06:20 | Bookings create none (re-enabled 2026-09-08 with no criteria) | Calls function sfaConfirm, which branches by Resource_Name (Bay -> template F6E1; Coach -> F7E1/F7ME1) and sends via the Bookings /actions/send_mail API. These emails are sent against the Booking record, so they appear on the Booking's Emails list, not the Contact's. "BOOKING EMAIL SEND FAILED" alerts to max@ are recipient-level blocks (unsubscribed, bad address, full inbox), not code faults. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfaconfirm.deluge; crm_email_templates/flows_bookings/sfaConfirm.deluge |
Lesson 48h Get-Ready6296422000045328011 | workflow rule | Active last run 2026-10-11T19:01 | date-based, 2 days before Start_Date_and_Time function-side: coach bookings only (Resource_Name contains Coach, excludes Evaluation) | Calls sfaReminder48, sends template F7E3/F7ME3. These emails are sent against the Booking record, so they appear on the Booking's Emails list, not the Contact's. "BOOKING EMAIL SEND FAILED" alerts to max@ are recipient-level blocks (unsubscribed, bad address, full inbox), not code faults. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfareminder48.deluge |
Lesson Day-Before6296422000045328020 | workflow rule | Active last run 2026-10-12T07:00 | date-based, 1 day before Start_Date_and_Time function-side: coach bookings only, same branch as 48h rule | Calls sfaReminderDayBefore, sends template F7E2/F7ME2. These emails are sent against the Booking record, so they appear on the Booking's Emails list, not the Contact's. "BOOKING EMAIL SEND FAILED" alerts to max@ are recipient-level blocks (unsubscribed, bad address, full inbox), not code faults. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfareminderdaybefore.deluge |
P3 Pre-Lesson Expectations Reminder6296422000046672013 | workflow rule | Inactive last run 2026-09-09T16:01 | date-based, 1 day before Start_Date_and_Time none logged; own description says liveCodes={} routes sends to max@ until go-live | Calls sfa3prelesson to send a separate pre-lesson expectations email (distinct copy from Lesson Day-Before). | CRM Setup > Automation > Workflow Rules > Bookings crm_functions_live/functions/sfa3prelesson.deluge |
Post-Session Follow-up6296422000045328029 | workflow rule | Inactive last run 2026-09-09T16:00 | date-based, 2 hours after End_Date_and_Time function-side branch by Booking_Details (eval/intro) or Resource_Name (bay/coach), nurture capped once per 60 days | Calls sfaPostSession, sends F3E1(eval)/F4E1(intro)/F6E2(bay)/F7E4-F7ME4(coach). | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfapostsession.deluge |
3 Days Nurture6296422000045328038 | workflow rule | Inactive last run 2026-09-09T16:00 | date-based, 3 days after End_Date_and_Time function-side: evaluation/intro bookings, or capped bay nurture for non-members | Calls sfaDay3 nurture email. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfaday3.deluge |
7 Days Nurture6296422000045328047 | workflow rule | Inactive last run 2026-09-09T16:00 | date-based, 7 days after End_Date_and_Time function-side: evaluation/intro bookings only | Calls sfaDay7 nurture email. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfaday7.deluge |
SFAbookingcancelled6296422000045556273 | workflow rule | Active last run 2026-10-11T18:44 | field update, Status becomes Cancelled Status = Cancelled | Calls sfaBookingCancelled, sends template T5, guarded against double-send with a staff-cancel flag (T3). Email_Sent is marked T5 only after a confirmed send; a failed send alerts max@. Before 2026-09-30 the send lacked org_email and no cancellation email was delivered. | CRM Setup > Automation > Workflow Rules > Bookings crm_functions_live/functions/sfaBookingCancelled.deluge |
SFAbookingRescheduled6296422000046337266 | workflow rule | Active last run 2026-10-11T17:49 | field update, any change to Start_Date_and_Time none beyond the field changing; guarded by Last_Reschedule_Sent cooldown (min 1 day) and skipped if Cancelled | Calls sfabookingreschedule, sends the reschedule confirmation template. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfabookingreschedule.deluge (function code has no descriptive header/comment - orphan) |
sfaSameDayBookingPing6296422000046337517 | workflow rule | Active last run 2026-10-12T06:20 | Bookings create none logged in the rule; same-day check is inside the function | Calls function sfaSameDayBookingPing, an internal staff notification for bookings made for the same day. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfasamedaybookingping.deluge |
Voucher Consumed in GM469029000000173061 (link voucher_consumed_in_gm) | flow | Disabled last run never (function | meant to fire on GM voucher consumption n/a - never went live | Would call UpdateCRMCredits_VoucherConsumption: look up the GM customer's email, find the CRM Contact, match an Active Credit record by name, and reduce its Balance by consumed units. | Zoho Flow > folder Golf Manager - Zoho CRM/BOOKS arch/flow_deluge_source (UpdateCRMCredits_VoucherConsumption) |
sfabookingsweep (rebookingsweepsfa330pm)6296422000045974193 | schedule | Active last run 2026-09-01T15:31 | daily 15:30 Asia/Dubai scans today's completed coach bookings (Resource_Name starts Coach, excludes Evaluation/Cancelled, ended >30 min ago) | For each, checks for an existing future lesson/practice booking and (for member tiers) practice-access usage; stamps Rebook_Lesson_Booked/Rebook_Practice_Booked/Stamped_Coach/Rebook_Alert_Time; emails an HTML digest to max@ and akash@ grouped by location/category. | CRM Setup > Automation > Schedules crm_functions_live/functions/sfabookingsweep.deluge |
sfabookingsweep (rebookingsweepsfa1030pm)6296422000048862640 | schedule | Active last run 2026-09-01T22:31 | daily 22:30 Asia/Dubai identical scan criteria to the 15:30 run | Runs the exact same sfabookingsweep function a second time in the same day - not documented in the raw trace, which only describes one ~15:30 run. | CRM Setup > Automation > Schedules crm_functions_live/functions/sfabookingsweep.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Bookings | Name | GM booking id, used as the upsert key from GolfManager | GM_ZCRM_BookingCreate_Upsert |
| Bookings | Resource_Name | Text description of the booked resource (Bay N / Coach X); drives every bay-vs-coach branch in this flow | GM_ZCRM_BookingCreate_Upsert |
| Bookings | Email_Sent | Short code (F6E1, F7E1, T5, etc.) stamped before each send, preventing duplicate sends | sfaConfirm, sfaReminder48, sfaReminderDayBefore, sfaBookingCancelled, etc. |
| Bookings | Last_Reschedule_Sent | Cooldown timestamp so reschedule emails don't fire more than once per day | sfabookingreschedule |
| Contacts | Next_Booking_Ref / Next_Session_Date / Next_Session_Coach / Last_Booking_Date | Roll-up of the contact's latest/next booking, read by staff and by the rebooking/coach digests instead of querying Bookings directly | syncContactBookings |
| Bookings | Rebook_Lesson_Booked / Rebook_Practice_Booked / Stamped_Coach / Rebook_Alert_Time | State stamped by the daily rebooking sweep so it doesn't re-flag the same booking | sfabookingsweep |
Full email text
Booking Confirmation - Bay (F6E1)Your SwingFIT bay is booked - Bookings.Start Date and Time
Booking Confirmation - Coach PAYG (F7E1)Your coaching session is booked - Bookings.Start Date and Time
Booking Confirmation - Coach Member (F7ME1)Your coaching session is booked - Bookings.Start Date and Time
Lesson Day-Before Reminder - Member (F7ME2)Your coaching session is tomorrow - Bookings.Start Date and Time
48h Get-Ready - PAYG (F7E3)Your session is in 48 hours - let's get you ready
48h Get-Ready - Member (F7ME3)Your session is in 48 hours - let's get you ready
IDs and references
| What | Value |
|---|---|
| CRM Bookings module id | 6296422000025762004 |
| CRM Evaluation Booking module id (referenced by branch logic) | 6296422000046081368 |
| Zoho Flow folder - Golf Manager integrations | 469029000000062289 (Golf Manager - Zoho CRM/BOOKS) |
| Rebooking digest recipients | max@swingfitacademies.com, akash@swingfitacademies.com |
All flows › No-show
When someone doesn't show up (no-show or late cancel)
A GolfManager no-show is designed to alert the coach, email eligible members, and create a Member Success follow-up task.
- Starts when
- A coach or front-desk staff member ticks the 'No show' checkbox on the booking in GolfManager, after the session time has passed and the player never turned up.
- Covers
- Covers a member/client missing a paid lesson or bay session, and a prospect missing a free evaluation/trial. Does not cover advance cancellations (handled elsewhere) or any monetary no-show fee — Max confirmed no-shows only ever cost the session credit, never cash.
- Systems
- GolfManager, Zoho CRM, Zoho Cliq
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Staff marks itGolfManager
Coach or front desk ticks 'No show' on the booking
Verified liveIn GolfManager's own booking screen there's a
No showcheckbox on every booking record. Staff tick it after the fact for a member/client lesson or bay session that was booked but never attended.See itGolfManager > Bookings > open the booking > 'No show' checkbox - T+0 (designed)Manual CRM stampZoho CRM
A 'Mark No-Show' button on the Player record can also stamp the session
From codeThe Players (Contacts) record layout has a
Mark No-Showbutton (sfaMarkNoShow). Pressing it finds that player's most recent Bookings record and stampsTrialnoshow_Stage,Trialnoshow_Stamped_AtandNoshow_Session_Dateon it.See itContacts (Players tab) > open the player > 'Mark No-Show' button - T+0 (designed)3 Bookings automations fireZoho CRM
Editing
From codeNoshow_Flagon a Bookings record is meant to fire three automations at onceAny edit to the
Noshow_Flagfield on a Bookings record (set to 'No-show' or 'Late-Cancel') is designed to trigger three separate CRM workflow rules in parallel: an internal Cliq alert, a member-facing policy reminder email, and a Member Success follow-up Task.- NOSHOW Internal AlertFrom codeT+0
sfanoshowalertposts 'No-show: member - resource, session date/time.' to the coach's own 1:1 Cliq chat (matched by first name in the resource name: Richard, Stian, Harry, Pradeep or Brad) and to a shared Member Success Cliq chat. Guarded byNoshow_Alert_Sentso it only fires once per booking. - NOSHOW Policy ReminderFrom codeT+0
sfanoshowpolicyremindersends an 'Everything okay?' email to the member, but only when the player's Lifecycle Status is Member, Beginner Member, 6 Month Member or Junior Member. Guarded byEmail_Sentcontaining 'NS1'. Also stampsNoshow_WA_Stageto 'Pending - WA push'. - NOSHOW Recovery TaskFrom codeT+0
sfaNoshowFollowupTaskcreates a CRM Task ('No-show follow-up: member') owned by the Member Success queue, due same day, so a human can claim it and call the member. Guarded byNoshow_Task_Created.
See itZoho CRM setup > Automation > Workflow Rules > module Bookings - daily 15:00Trial/eval sweepZoho CRM
A separate daily sweep handles trial/evaluation no-shows on a 2-step timer
From codesfaTrialNoshowSweep(schedule 'sfaTrialNoshowSweep Schedule', daily 15:00) runs a 2-stage recovery: bookings atTrialnoshow_Stage0 whose session ended ≥1 day ago get a first recovery email and move to stage 1; bookings sitting at stage 1 for ≥2 days get a second recovery email and move to stage 2.See itZoho CRM setup > Automation > Schedules > 'sfaTrialNoshowSweep Schedule' - daily 09:30Re-engagement handoff (as documented)Zoho CRM
Trial no-shows are documented to hand off into the Phase C re-engagement drip
UnverifiedThe sweep's own description says it 'stamps Trialnoshow_Stage for Phase C RE-P handoff' into
sfaRePSweep(schedule 'sfaRePSweep_Daily', daily 09:30), a 3-step re-engagement email sequence for unconverted prospects.See itZoho CRM setup > Automation > Schedules > 'sfaRePSweep_Daily'
Emails and messages
TeamNOSHOW Internal AlertUnverifiedn/a — Cliq chat message, not email
Full text (arch/crm_deluge_source/sfanoshowalert.deluge)
CustomerNOSHOW Policy ReminderUnverifiedEverything okay?
Full text (crm_email_templates/flows/Flow-NOSHOW_PolicyReminder.html)
CustomerTRIALNOSHOW Step 1 / Step 2 recovery emailsUnverified(recovery email subject, per template)
Full text (not found)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did the coach get pinged about a no-show? | Coach's own Cliq 1:1 chat, and the shared Member Success Cliq chat | A 'No-show: member - resource, date/time.' message appears within seconds of Noshow_Flag being edited on the Bookings record |
| Did the member get the policy reminder email? | Contacts > the player's record > Emails related list | An 'Everything okay?' email from info@swingfitacademies.com appears, sent_time close to the no-show, with Email_Sent on the Bookings record containing 'NS1' |
| Did Member Success get a follow-up task? | Tasks module, or the player's Contacts record > Tasks related list | A Task titled 'No-show follow-up: member' owned by Member Success, due the same day |
| Is the GolfManager 'No show' tick actually reflected anywhere in the CRM? | Zoho CRM > Bookings module > the matching record > Noshow_Flag field | Noshow_Flag shows 'No-show' or 'Late-Cancel' matching what was ticked in GolfManager |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Coach + Member Success Cliq alert | Zoho CRM setup > Automation > Workflow Rules > Bookings > 'NOSHOW Internal Alert' (currently OFF, renamed ZZOFF-2026-09 NOSHOW Internal Alert) | No Cliq message to the coach or Member Success chat when Noshow_Flag is edited |
| Member policy reminder email | same list > 'NOSHOW Policy Reminder' (currently OFF, renamed ZZOFF-2026-09 NOSHOW Policy Reminder) | Customer never receives the 'Everything okay?' email |
| Member Success follow-up Task | same list > 'NOSHOW Recovery Task' (currently OFF, renamed ZZOFF-2026-09 NOSHOW Recovery Task) | No Task is created for Member Success to claim |
| Trial/eval 2-step recovery sweep | Zoho CRM setup > Automation > Schedules > 'sfaTrialNoshowSweep Schedule' | Daily sweep stops stamping Trialnoshow_Stage and stops attempting the recovery emails |
Good to know
No-shows never cost money, only a credit
Max confirmed on 2026-07-15 that a no-show or late cancel only consumes the booking credit — there is no cash fee. GolfManager does not reverse the sale or refund the credit when a booking is marked No Show; it stays billed exactly as if the session had happened.
Two separate no-show tracks by design
Member/client lesson no-shows are meant to run off the Noshow_Flag field on Bookings (alert + email + task, all field-edit triggered). Trial/evaluation no-shows run off a separate Trialnoshow_Stage counter on the same Bookings module, processed by a daily time-based sweep instead.
Who is eligible for the policy email
By design, only players whose Lifecycle Status is Member, Beginner Member, 6 Month Member or Junior Member receive the policy reminder — churned members, leads and pay-as-you-go clients are intentionally excluded.
Coach chat routing is name-matched
The internal alert is designed to reach the coach's personal Cliq chat by matching a first name inside the GolfManager resource name (e.g. 'Member Coach Pradeep (DIFC)' routes to Pradeep), plus a shared Member Success chat every time.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (6)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Mark No-Show6296422000047316029 (Players custom button, function sfamarknoshow) | button | Button last run n/a - no per-cli | manual click none | Finds the player's most recent Bookings record and stamps Trialnoshow_Stage, Trialnoshow_Stamped_At, Noshow_Session_Date - never Noshow_Flag, so it cannot trigger any of the three Noshow_Flag-based rules below. Own description: 'Shell only -- email send logic pending Max's review'. | Contacts (Players tab) > player record > Mark No-Show button arch/crm_deluge_source/sfamarknoshow.deluge |
NOSHOW Internal Alert6296422000047316082 | workflow rule | Inactive last run 2026-08-30T10:53 | field update, Noshow_Flag = 'No-show' Noshow_Flag equals No-show | Calls sfanoshowalert, which posts 'No-show: member - resource, date/time.' to the coach's own Cliq chat (name-matched: Richard/Stian/Harry/Pradeep/Brad) and a shared Member Success Cliq chat. Guarded by Noshow_Alert_Sent (once per booking). | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfanoshowalert.deluge |
NOSHOW Policy Reminder6296422000047316066 | workflow rule | Inactive last run 2026-07-16T07:18 | field update, Noshow_Flag not empty Noshow_Flag != empty (function itself further restricts to Lifecycle Status Member/Beginner Member/6 Month Member/Junior Member) | Calls sfanoshowpolicyreminder, sends the 'Everything okay?' email; also stamps Noshow_WA_Stage='Pending - WA push'. send_mail body has no org_email:true flag (known Aug-2026 defect class). | CRM Setup > Automation > Workflow Rules > Bookings crm_functions_live/functions/sfanoshowpolicyreminder.deluge |
NOSHOW Recovery Task6296422000052132175 | workflow rule | Inactive last run 2026-08-30T10:53 | field update, Noshow_Flag = 'No-show' Noshow_Flag equals No-show (sibling criteria to Internal Alert) | Calls sfaNoshowFollowupTask, creates a Task 'No-show follow-up: member' owned by Member Success, due same day. Guarded by Noshow_Task_Created. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfanoshowfollowuptask.deluge |
sfaTrialNoshowSweep Schedule6296422000047217152 | schedule | Active last run 2026-09-01T15:05 | daily 15:00 Asia/Dubai Stage-0 branch: zoho.crm.searchRecords(CustomModule6, Trialnoshow_Stage:equals:0) with NO no-show/evaluation filter at all - matches virtually every untouched Bookings record (harmless today only because testMode is hardcoded true and both template ids are literal placeholder strings). Stage-1 branch: records sitting at stage 1 for >=2 days. | 2-stage recovery: stage 0 -> sends Step 1 recovery email and moves to stage 1 (>=1 day after session end); stage 1 -> sends Step 2 and moves to stage 2 (>=2 more days). | CRM Setup > Automation > Schedules arch/crm_deluge_source/sfatrialnoshowsweep.deluge |
sfaRePSweep_Daily6296422000047420268 | schedule | Active last run 2026-09-02T09:31 | daily 09:30 Asia/Dubai Phase C RE-P: targets Prospect/Prospect-Non-Converted leads; skips anyone onboarded <30 days ago, in card-update dunning, card expiring in 0-10 days, or already in another nurture track | 3-step re-engagement email sequence (RE-P-E1/E2/E3, 7-day spacing via RE_P_Stage). Despite sfaTrialNoshowSweep's own description claiming it 'stamps Trialnoshow_Stage for Phase C RE-P handoff', sfarepsweep.deluge's entry criteria never reference Trialnoshow_Stage anywhere (grepped both archive copies, zero matches) - the two pipelines are not actually connected in code. | CRM Setup > Automation > Schedules arch/crm_deluge_source/sfarepsweep.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Bookings | Noshow_Flag | 'No-show' or 'Late-Cancel'; the single field the three Bookings-module no-show automations are designed to trigger on | Designed to be written by GolfManager's own no-show status via a sync (not yet built; see fix_additions) or by staff editing the field directly in CRM |
| Bookings | Noshow_Alert_Sent / Noshow_Task_Created | Guard flags preventing the Internal Alert / Recovery Task from firing twice on the same booking | sfanoshowalert / sfaNoshowFollowupTask |
| Bookings | Trialnoshow_Stage | 0/1/2 counter driving the 2-step trial/eval recovery sweep | sfaMarkNoShow (sets to 1 directly, skipping stage 0) or sfaTrialNoshowSweep (advances 0->1->2) |
| Bookings | Noshow_WA_Stage | Set to 'Pending - WA push' on every policy-reminder send, apparently staged for a WhatsApp follow-up that was never built - nothing else in the archive reads this field | sfanoshowpolicyreminder |
| Bookings | Noshow_Session_Date | Session date stamped for use in the policy reminder's merge fields | sfaMarkNoShow |
IDs and references
| What | Value |
|---|---|
| NOSHOW Policy Reminder rule id | 6296422000047316066 |
| NOSHOW Internal Alert rule id | 6296422000047316082 |
| NOSHOW Recovery Task rule id | 6296422000052132175 |
| Mark No-Show custom button id | 6296422000047316029 |
All flows › Lesson report
After a lesson: the coach's lesson report and the evaluation outcome/debrief
A coach's session or evaluation report is logged in CRM, which files the coaching data, tries to email the player, and schedules follow-up progress reports.
- Starts when
- A coach submits the Lesson Report Zoho Form after a Lesson/Fitness session, or completes the Eval Outcome / Eval Debrief Zoho Form after a Golf Evaluation.
- Covers
- Covers what happens after a coached Lesson/Fitness session or a Golf Evaluation: how the coach gets the report/debrief form, the CRM write-back, the resulting player and coach emails, and where staff can verify a report or debrief actually landed. Does not cover the booking itself, the pre-session eval intake form, or member sign-up/billing.
- Systems
- Zoho CRM, Zoho Flow, Zoho Forms, Zoho Cliq, Website
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0 (booking created/edited)Booking savedZoho CRM
The booking gets its own prefilled report-form link
Verified liveThe
sfaStampLessonFormURLworkflow rule (Bookings, create/edit) stamps a prefilled Lesson Report form URL onto the booking record, guarded so it never re-stamps a booking that already has one. A check every 2 hours (sfaLessonFormURLSweep) adds the link to any coaching booking that still has none, because bookings finished off by the GolfManager sync never pass through that rule.See itBookings record > Lesson Report Form URL field; also visible as a column on the Player's 'Player Booking History' related list (page must be freshly reloaded to show it). A booking created in the last 2 hours may not have it yet; the check fills it in. - daily 7:30am DubaiCoach morning digestZoho Cliq
Coach gets today's report links pushed to them
From codesfaCoachMorningDigest(daily schedule) lists each coach's sessions for the day and DMs them via the Coach Digest Bot (postToBot, Organization-scoped), with an identical email sent in parallel as a fallback in case the Cliq message doesn't arrive. Each Lesson/Fitness session line carries that booking's prefilled Lesson Report form link (its ownsfaStampLessonFormURLlink). Evaluation bookings are listed too but carry no form link here - the eval debrief link is delivered separately, see below.See itCliq DM from Coach Digest Bot each morning; coach's inbox for the parallel email if Cliq doesn't arrive. - any timeCoach's My sessions pageWebsite
Coach opens their own 'My sessions' page
Verified liveEach coach has a private link (saved to their phone's home screen) to system.swingfitacademies.com/coaches/my-sessions.php. It lists their sessions from the last 7 days and today, read live from CRM every time the page is opened. Lessons show a 'Fill in' button (prefilled Lesson Report) until a report is logged; evaluations show a 'Debrief' button (prefilled Eval Debrief) until the debrief is logged; practice and 'Play with your Pro' sessions show 'No report needed'. A 'blank report' button covers anything not listed. It does not depend on Cliq or email, so it is the route to use when a digest or debrief message never arrived.
See itOpen the coach's link: the count at the top shows reports/debriefs still to do; a tick means CRM has the report (Lesson_Reports linked to the booking, or Bookings.Report_Logged) or the debrief (Evaluation_Booking.Session_Happened filled). - T+0 (session end)Coach submits Lesson ReportZoho Forms
Coach fills in the Lesson Report form
Verified liveCoach opens the prefilled link and records: session happened / no-show, primary domain + focus taxonomy (club/shot/mechanic), next focus, rebooking outcome, challenge attempted/result, on-course score, coach note, and the OnForm video link for this lesson (a new video each lesson).
See itn/a — form submission itself has no CRM trace until the next step. - T+secondsForm -> FlowZoho Flow
Form submission runs a Zoho Flow into CRM
From codeZoho Forms 'Form entry submitted' trigger on the Lesson Report Flow v2 flow (live, not disabled) calls the flow's Custom Function
LessonReportRun4, which packages the form fields and makes a GET webhook call to the CRM functionsfacreatelessonreport.See itflow.zoho.com > Lesson Report Flow v2 > run history. - T+secondsLesson_Reports record createdZoho CRM
From codesfaCreateLessonReportbuilds and files the reportLooks up the booking and player, resolves the coach from the booking's resource, builds
Focus_Areafrom the domain/club/mechanic taxonomy, and setsCompletion_Statusby rule (since 30 Sep 2026): a golf lesson is 100% Complete when it has a real OnForm video link (link.getonform.com/view?id=...orvideoplayer.onform.com/v/...) that has not been used on another lesson; the rebooking answer is recorded but does not affect the status. A fitness session is 100% Complete once the report is submitted. A no-show gets its own No-show status: not 100% Complete, but it counts as a lesson delivered. Anything else is Incomplete. It also stores the video id (OnForm_Id), tries to auto-assign a matching Drill_Library and Knowledge_Library entry, stamps the player'sEmail, and creates the record withtrigger:{workflow}so downstream workflow rules fire.- A reused video link is rejectedFrom code
Before filing, the function looks up the video id on earlier reports. If the same video is already on a report for a different lesson, the link does not count and the report is Incomplete. Resubmitting a report for the same lesson is not treated as reuse.
- Coach gets a copy of the report on CliqFrom code
The coach receives their report via the Coach Digest Bot, including the completion status. If the video link was rejected, the message names the lesson it was already used on and adds a 'Resubmit here' link: that booking's prefilled Lesson Report form. The coach resubmits with a new video for that lesson.
- Client email pathFrom code
A
// TODO Phase 4comment in the function marks a planned path where it would trigger the player's progress email directly; today that email is sent by the native CRM workflow rule described in the next step instead.
See itLesson_Reports record itself (Coach, Focus_Area, Completion_Status, Assigned_Drill fields). - T+0 on Lesson_Reports createTwo rules fire togetherZoho CRM
Report gets logged and the player's progress email is triggered
UnverifiedTwo active workflow rules fire on every Lesson_Reports create:
sfaStampReportLoggedstampsBookings.Report_Loggedand the report's ownSubmitted_Atwith the report's creation time (so coaches/staff can see a report actually landed), andT3 Post-Lesson Progressfires an Email Notification meant to send the player their session recap.See itBookings > Report_Logged field (dated); Lesson_Reports > Submitted_At. - variesEval Outcome formZoho Forms
Coach records the evaluation outcome
From codeFor a Golf Evaluation, the coach's Eval Outcome form submission runs the Eval Outcome to CRM flow (live) into
EvalOutcomeRun, which GETs the CRM functionsfacreatememberplanwith goal, current/goal level, on-form link and score.See itflow.zoho.com > Eval Outcome to CRM > run history. - T+secondsMember_Plan created/updatedZoho CRM
Verified livesfaCreateMemberPlansets up the player's planCreates a Member_Plan for a first-time player or updates the existing one: sets Goal/Current_Level/Goal_Level, membership status from the player's Lifecycle_Status, stamps the player's
Email(for the plan/expectations email) and a permanentRound_Log_Link.See itMember_Plan record for the player. - on End_Date_and_Time (0 offset)Eval endsZoho CRM
Coach is sent the debrief form link
Verified liveCoach Post-Session Debrief Send(Evaluation_Booking, live) fires the moment the eval's End_Date_and_Time passes, runningsfaEvalDebriefSend, which DMs the coach a prefilled Eval Debrief form link via the same Coach Digest Bot used by the morning digest (switched from Max's personal Cliq DM to the bot on 2026-09-21). Hardening skips Brad, duplicate names, non-eval and no-show bookings.See itCliq DM from Coach Digest Bot right after the eval's scheduled end time. - variesCoach submits Eval DebriefZoho Forms
Coach fills in the debrief
Verified liveCoach records Session_Happened (Yes/No-show), the offer made, the player's decision, and debrief completion.
See itn/a until the webhook below runs. - T+secondsDebrief -> CRM webhookZoho Flow
Debrief form writes back to the eval booking
Verified liveZoho Forms 'Form entry submitted' on the 'Eval Debrief' form runs the Eval Debrief to CRM (Send Webhook) flow, a GET webhook straight to the CRM function
sfalogevaldebrief(no intermediate custom function). It writes Session_Happened, Offer_made, Decision and Eval_Debrief_Completion onto the Evaluation_Booking record, stamps the booking's Email field, and creates a Player_Roadmap record.See itEvaluation_Booking record's Session_Happened/Offer_made/Decision fields; related Player_Roadmap record. - on Session_Happened field updateClient recap email (intended)Zoho CRM
Client is meant to get a debrief recap + next-step email
UnverifiedThe
Eval Debrief - Send Recap Emailworkflow rule is designed to watch for any change to Session_Happened on Evaluation_Booking and send the 'Eval Debrief - Client Recap' email to the player.See itContact's Emails related list for 'Eval Debrief - Client Recap' / 'Eval Debrief - Recap Next Step' template. - daily / every 30 then 90 days per planProgress reportZoho CRM
Member gets a periodic progress report
Unverifiedsfaprogressreportsend(daily schedule, testMode=false/live since 2026-08-13) scans Member_Plan for players due a report (30 days after first logged session, then every 90), scores them across the five coaching domains from Lesson_Reports Challenge_Result evidence, creates a Progress_Reports record, and emails it. Holds (does not send) if no domain has evidence yet, or if the player is in card-update dunning.See itProgress_Reports related list on the Member_Plan; Contact's Emails related list.
Emails and messages
CustomerT3 Post-Lesson Progress (Lesson / Fitness)UnverifiedPlayer — your video + what's next
CustomerEval Debrief - Client RecapUnverifiedtemplate: Eval Debrief - Recap Next Step
Full text (not found)
TeamsfaCoachMorningDigestVerified liven/a (Cliq message) / coach's daily session list (email fallback)
TeamsfaEvalDebriefSend (coach debrief-form link)Verified liven/a (Cliq message)
CustomerProgress ReportUnverified'PP-B03' template
Full text (crm_email_templates/PROGRESS-Report.html)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did the coach's lesson report actually go in? | Booking record > Report_Logged field (stamped with the report's Created_Time), or the Player Booking History related list on the player's Contact. | Report_Logged carries a timestamp close to the session's end time. |
| Why is a lesson report Incomplete? | Lesson_Reports record > OnForm Link / OnForm Id / Completion Status; the coach's Cliq copy of the report says why. | Incomplete means no OnForm link, a link that isn't a real OnForm video, or a video already used on another lesson. The coach resubmits from the 'Resubmit here' link with a new video. |
| Did the client get their post-lesson video/next-focus email? | Player's Contact > Emails related list. | A 'your video + what's next' email on the player's Contact record, sent to the player's own address. |
| Did the coach get the report-form link for today's sessions? | Cliq: Coach Digest Bot DM around 7:30am; fallback is an email to the coach. | Each Lesson/Fitness line has a form link; if a coach reports nothing arrived, check the roster in sfaCoachMorningDigest and the coach's Cliq subscription status. |
| A coach says no form or debrief link reached them. Where do they go? | Their 'My sessions' page (private link per coach, held by Max). | The session is listed with a Fill in / Debrief button. If it is missing from the page, the booking has no coach on it yet in CRM (the hourly GolfManager sync fills this in); use the blank report button meanwhile. |
| Did the eval debrief form reach the coach? | Cliq: Coach Digest Bot DM right after the eval's scheduled end time. | One message per eval, skipping Brad, duplicate names, non-evals and no-shows by design. |
| Did the client get an eval debrief recap / next-step email? | Player's Contact > Emails related list. | An 'Eval Debrief - Client Recap' email on the player's Contact record, dated close to when the debrief was logged. |
| Is a workflow rule actually live, or was it caught in the 09-09 mass switch-off? | CRM Setup > Automation > Workflow Rules — check the name has no 'ZZOFF-2026-09' prefix and status is Active. | Active + no ZZOFF prefix; also compare last_executed_time to recent activity on that module. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Player-facing post-lesson email (T3 Post-Lesson Progress) | CRM Setup > Automation > Workflow Rules > 'T3 Post-Lesson Progress' (Lesson_Reports) — deactivate the rule. | Stops both the Lesson and Fitness Email Notifications from firing; sfaStampReportLogged (report-logged stamp) is a separate rule and keeps running. |
| Coach report-form link on bookings | CRM Setup > Automation > Workflow Rules > 'sfaStampLessonFormURL' (Bookings) — deactivate. | New/edited bookings stop getting a Lesson Report Form URL; existing links are unaffected. |
| Coach morning digest | CRM Setup > Automation > Schedules > 'sfaCoachMorningDigest' — deactivate the schedule. | No more daily Cliq DM or email fallback to coaches; they'd need the report-form link from the booking's own field instead. |
| Eval debrief link to the coach | CRM Setup > Automation > Workflow Rules > 'Coach Post-Session Debrief Send' (Evaluation_Booking) — deactivate. | Coaches stop getting the prefilled Eval Debrief link after a session ends. |
| Eval client recap email | CRM Setup > Automation > Workflow Rules > 'Eval Debrief - Send Recap Email' (Evaluation_Booking) — deactivate. | Stops the client recap email path entirely. |
| Progress report | CRM Setup > Automation > Schedules > 'sfaprogressreportsend' — deactivate the schedule. | Stops the 30/90-day progress report scan and email entirely. |
Good to know
Two different 'debrief' mechanisms, don't confuse them
A Lesson/Fitness session uses the Lesson Report form (LessonReportRun4 -> sfaCreateLessonReport). A Golf Evaluation uses two separate forms/flows: Eval Outcome (-> sfaCreateMemberPlan, sets up the plan) and Eval Debrief (-> sfaLogEvalDebrief, records what was offered and decided). There is no 'Evaluation_Reports' CRM module — evaluations write into Evaluation_Booking and Member_Plan, not Lesson_Reports.
The coach's report-form link lives on the booking, not the player
sfaStampLessonFormURL stamps a unique prefilled link onto each booking (self-guarded so it never re-stamps once set), which is what both the morning digest and the Player Booking History column surface.
Completion_Status has real logic behind it
Rule since 30 Sep 2026. Golf lesson: 100% Complete = a real OnForm video link that has not been used on another lesson (rebooking no longer counts). Fitness: 100% Complete once submitted. No-show: its own status, not 100% Complete, but it counts as a lesson delivered. Two numbers come straight from this field: '100% Complete', and 'Lessons delivered' = 100% Complete + No-show. Only 100% Complete reports move a player's plan forward.
sfaCreateLessonReport / sfaCreateMemberPlan create records with an explicit trigger flag
Both stamp the player's Email onto the new record on purpose, specifically so a native CRM workflow email notification (T3, and the eval-side plan/expectations email) can use a real Email field to send from — Bookings has no Email field of its own.
Drill/Knowledge auto-assign depends on an exact taxonomy match
Drill_Library.Focus_Area and Knowledge_Library.Focus_Area_Domain must match the report's computed Focus_Area string (e.g. 'Full Swing > Irons > Release') exactly, and only an Active drill/insight at the player's Current_Level qualifies — if nothing matches, Assigned_Drill/Assigned_Knowledge are simply left blank.
How the 'My sessions' page stays up to date
Nothing to run or sync: the page reads CRM live on every open or refresh. New bookings appear once they are in CRM with a coach attached; ticks appear within about a minute of a form being submitted; the 7-day window rolls forward by itself. Manual changes are needed only when (1) a coach joins or leaves, or gets a new GolfManager resource: update the roster in sfaCoachSessionsFeed AND sfaCoachMorningDigest so the two stay in sync; (2) a new coach needs a link: add a private code in my-sessions.php; (3) the Lesson Report or Eval Debrief form itself is replaced by a new form (new address).
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (15)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
sfaStampLessonFormURL6296422000052535022 | workflow rule | Active last run 2026-10-12T06:20 | Bookings create or edit (repeatable) self-guarded: never re-stamps a booking that already has a link | Stamps a prefilled Lesson Report Zoho Form URL onto the booking record, surfaced on the morning digest and the Player Booking History related list. | CRM Setup > Automation > Workflow Rules > Bookings not in the 2026-09-02 archive - built 2026-09-07, after capture; read live only |
sfaLessonFormURLSweepschedule sfaLessonFormURLSweep (function api sfalessonformurlsweep) | schedule | Active last run runs hourly | every 2 hours (Zoho minimum; from 2026-09-29 17:15 Asia/Dubai; first run confirmed) Bookings with no Lesson Report Form URL, 30 days back to 120 days ahead, on a coach/fitness resource, coached product only (Coaching / Lesson / Intro to Golf / Fitness); skips evaluations, practice/Play with your Pro and cancelled | Stamps the prefilled Lesson Report link onto any booking the create/edit rule missed. Needed because the hourly GolfManager reconcile fills the coach and product with workflows off, so the create/edit rule never sees the finished booking. Writes with workflows off; no sends. | CRM Setup > Automation > Schedules domains/coaching/my-sessions/sfaLessonFormURLSweep-2026-09-29.deluge |
sfaCoachMorningDigest6296422000046337495 | schedule | Active last run 2026-09-02T07:31 | daily 07:30 Asia/Dubai lists each coach's sessions for the day | DMs each coach via the Coach Digest Bot (postToBot, Organization-scoped) with today's session list; Lesson/Fitness lines carry the sfaStampLessonFormURL link. Also sends an identical email in parallel as a backup delivery path alongside the Cliq DM. Evaluation sessions are listed with no form link (that comes separately from Coach Post-Session Debrief Send). | CRM Setup > Automation > Schedules arch/crm_deluge_source/sfacoachmorningdigest.deluge |
sfaCoachSessionsFeedapi sfacoachsessionsfeed (REST API, API key) | function | Active last run runs on every pa | called by the My sessions page each time a coach opens or refreshes it (PHP server-side proxy; the API key lives only in the server copy of the PHP, never in the browser or the repo) coach key must match the roster (richard, stian, harry, pradeep, henry); each coach's private link code maps to a key inside my-sessions.php. Window: 7 days ago to end of today, non-cancelled bookings on that coach's resources (same resource roster as sfaCoachMorningDigest). Read-only: no writes, no sends. | Returns the coach's sessions with a kind (lesson / evaluation / practice), a prefilled Lesson Report link built on the fly (independent of the stamped Bookings.Lesson_Report_Form_URL), a logged flag (Lesson_Reports by Booking.id or Bookings.Report_Logged), and for evaluations a prefilled Eval Debrief link (same params as sfaEvalDebriefSend) matched via Evaluation_Booking.GM_Booking_Id = Bookings.Name, logged = Session_Happened filled. | CRM Setup > Developer Hub > Functions (standalone); called only by public_html/system/coaches/my-sessions.php on the Hostinger system site domains/coaching/my-sessions/sfaCoachSessionsFeed-2026-09-29.deluge (v2, live); my-sessions.php (repo copy has the API key placeholder); coach link codes in coach-tokens.json |
Lesson Report Flow v2469029000000321143 (link lesson_report_flow_v2) | flow | Active last run 2026-09-21T09:52 | Zoho Forms 'Form entry submitted' on the Lesson Report form none | Calls custom function LessonReportRun4, which packages the form fields and makes a GET webhook call to the CRM function sfacreatelessonreport. | Zoho Flow > folder default LessonReportRun4 not in the 2026-09-02 archive (LessonReportRun/LessonReportRun3 are present but superseded) - built after capture, read live only |
sfaCreateLessonReport1446733000000646001 (api sfacreatelessonreport) | function | Live last run 2026-09-21T09:52 | called by the flow above n/a | Looks up the booking/player, resolves the coach from the booking's resource, builds Focus_Area, and sets Completion_Status: Lesson = '100% Complete' if the OnForm link contains 'getonform.com/view?id=' or 'videoplayer.onform.com/v/' AND that video id (parsed into OnForm_Id) is not on any Lesson_Reports record for a different Booking (searchRecords OnForm_Id equals); rebooking recorded in Rebooking_OK but no longer gates. Fitness = '100% Complete' on submission. No-show = 'No-show'. Else 'Incomplete'. Writes OnForm_Id. Auto-assigns Drill/Knowledge, stamps the player's Email, creates the record with trigger:{workflow}. Posts the coach a report copy via coachdigestbot; if the link was reused it adds the reason and 'Resubmit here: ' + Bookings.Lesson_Report_Form_URL. Member_Plan progress only increments on '100% Complete'. | CRM standalone function, called by Lesson Report Flow v2 crm_email_templates/flows_bookings/sfaCreateLessonReport_LIVE_2026-09-30.deluge (current, read back from the live editor by SHA-256 on 2026-09-30); _LIVE_2026-09-21 superseded |
sfaStampReportLogged6296422000052565031 | workflow rule | Active last run 2026-10-11T19:55 | Lesson_Reports create none | Stamps Bookings.Report_Logged and the report's own Submitted_At with the report's creation time. | CRM Setup > Automation > Workflow Rules > Lesson_Reports not in the 2026-09-02 archive - built 2026-09-08, after capture; read live only |
T3 Post-Lesson Progress6296422000046774054 | workflow rule | Active last run 2026-10-11T19:55 | Lesson_Reports create or edit none | Fires two native CRM Email Notifications ('T3 Post-Lesson Progress - Lesson' and '- Fitness') meant to send the player their session recap/video. Both have their 'To' hardcoded to Max Persson instead of the player's Email field - 4 prior API attempts to repoint 'To' failed with 'Selected recipient is unavailable.' | CRM Setup > Automation > Workflow Rules > Lesson_Reports CRM Setup > Automation > Email Notifications, folder 'Coaching Emails'; copy source crm_email_templates/SFA-P2-P3-T3-CopyStation.html |
Eval Outcome to CRM469029000000321103 (link eval_outcome_to_crm) | flow | Active last run per flow modific | Zoho Forms 'Form entry submitted' on the Eval Outcome form none | Calls custom function EvalOutcomeRun, which GETs the CRM function sfacreatememberplan with goal, current/goal level, on-form link and score. | Zoho Flow > folder default arch/raw_capture/flow_functions.json (function EvalOutcomeRun) |
sfaCreateMemberPlan1446733000000647020 (api sfacreatememberplan) | function | Live last run not separately t | called by the flow above n/a | Creates a Member_Plan for a first-time player or updates the existing one (Goal/Current_Level/Goal_Level, membership status from Lifecycle_Status, player's Email, a permanent Round_Log_Link). The existing-plan update path (and possibly the new-plan create path) calls zoho.crm updates with no explicit trigger:workflow option, meaning the P2 plan/expectations email likely never fires for a player's 2nd+ evaluation. | CRM standalone function, called by Eval Outcome to CRM arch/crm_deluge_source/sfacreatememberplan.deluge |
Coach Post-Session Debrief Send6296422000052132373 | workflow rule | Active last run 2026-10-11T16:00 | date-based, 0-day offset on End_Date_and_Time function-side hardening: skips coach Brad, skips ambiguous duplicate-name Bookings matches, skips non-eval bookings (neither Resource_Name nor Booking_Details mentions Evaluation), skips No-Show | Calls sfaEvalDebriefSend, which DMs the coach a prefilled Eval Debrief form link via the Coach Digest Bot (postToBot) - switched from Max's personal Cliq DM to the bot on 2026-09-21. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking crm_email_templates/flows_bookings/sfaEvalDebriefSend_BOT_2026-09-21.deluge (current live version; earlier LIVE_2026-08-30 and DRAFT copies superseded) |
Eval Debrief to CRM (Send Webhook)not found in 2026-09-02 archive flows_capture.json | flow | Live last run 2026-09-23T07:03 | Zoho Forms 'Form entry submitted' on the Eval Debrief form none | A GET webhook straight to the CRM function sfalogevaldebrief, no intermediate custom function. | Zoho Flow (built after 2026-09-02 capture) not in the 2026-09-02 archive - built after capture, read live only |
sfaLogEvalDebrief1446733000000775017 (api sfalogevaldebrief) | function | Live last run 2026-09-23T07:03 | called by the flow above n/a | Writes Session_Happened/Level_Confirmed/Roadmap_Matches_Goal/Coach_Focus_Finding/Offer_made/Decision/Recommended_Path/Loss_reason/Handover_Note/Eval_Debrief_Completion onto the Evaluation_Booking via zoho.crm.updateRecord with NO trigger:{workflow} option on either updateRecord call, stamps the booking's Email field, and (for a real session) creates a Player_Roadmap record with a coach-confirmed summary. | CRM standalone function, called by Eval Debrief to CRM webhook crm_email_templates/flows_bookings/sfaLogEvalDebrief_LIVE_2026-09-02.deluge |
Eval Debrief - Send Recap Email6296422000052085060 | workflow rule | Active last run 2026-08-31T15:05 | field update, Session_Happened = 'Yes' Session_Happened equals Yes (No-Show never matches, by design) | Meant to fire the native Email Notification 'Eval Debrief - Client Recap' on Session_Happened = 'Yes'. sfaLogEvalDebrief's updateRecord calls omit trigger:workflow, so this rule's field-update trigger does not see the change. | CRM Setup > Automation > Workflow Rules > Evaluation_Booking CRM Setup > Automation > Email Notifications on Evaluation_Booking - no dedicated HTML template file found anywhere in crm_email_templates |
sfaprogressreportsend6296422000046817894 (api sfaprogressreportsend_1) | schedule | Off last run 2026-09-01T11:15 | daily 11:15 Asia/Dubai Member_Plan where Sessions_Logged>0, due at day 30 (no Last_Progress_Report_Sent yet) or every 90 days after; holds (does not send) if no domain has evidence yet or the player is in card-update dunning | Scores the player across 5 coaching domains from Lesson_Reports Challenge_Result evidence, creates a Progress_Reports record, and emails it using template 'PP-B03'. | CRM Setup > Automation > Schedules crm_functions_live/functions/sfaprogressreportsend.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Bookings | Lesson Report Form URL | Unique prefilled Lesson Report form link for that specific booking, stamped once and never re-stamped | sfaStampLessonFormURL |
| Bookings | Report_Logged | Timestamp proving a Lesson Report actually landed for this booking | sfaStampReportLogged |
| Lesson_Reports | Focus_Area | Computed taxonomy string (e.g. 'Full Swing > Irons > Release') used to auto-match Drill_Library/Knowledge_Library entries | sfaCreateLessonReport |
| Lesson_Reports | Completion_Status | '100% Complete' (lesson: real, unreused OnForm video link; fitness: submitted) / 'No-show' (counts as delivered, not 100%) / 'Incomplete'. 36 September reports re-stamped to the new rule on 2026-09-30 with workflows off. | sfaCreateLessonReport |
| Lesson_Reports / Evaluation_Booking / Member_Plan | Email | Player's email stamped onto the record specifically so a native CRM Email Notification (which has no other path to the player's address) can send from it | sfaCreateLessonReport, sfaCreateMemberPlan, sfaLogEvalDebrief |
| Evaluation_Booking | Session_Happened / Offer_made / Decision / Eval_Debrief_Completion | What the coach's debrief recorded - outcome, offer made, and the player's decision | sfaLogEvalDebrief |
| Member_Plan | Round_Log_Link | Permanent link stamped once per plan | sfaCreateMemberPlan |
| Lesson_Reports | OnForm_Id (OnForm Id) | Video id parsed from the OnForm link; used to spot the same video on another lesson. Field id 6296422000054967030, created and backfilled on 238 reports 2026-09-30. | sfaCreateLessonReport |
Full email text
T3 Post-Lesson Progress - LessonLesson_Reports.Player.First_Name - your video + what's next
P2 Plan & Expectations - Member (eval-side plan email)Member_Plan.Player.First_Name, here's your plan
IDs and references
| What | Value |
|---|---|
| Lesson Report Flow v2 (Zoho Flow) id | 469029000000321143 |
| Eval Outcome to CRM (Zoho Flow) id | 469029000000321103 |
| T3 Post-Lesson Progress rule id | 6296422000046774054 |
| Eval Debrief - Send Recap Email rule id | 6296422000052085060 |
| Coach Post-Session Debrief Send rule id | 6296422000052132373 |
| Eval Debrief form (Zoho Forms) URL | https://forms.zohopublic.com/swingfitacademies1/form/EvalDebrief/... (formperma, prefilled per booking) |
| Coach My sessions page | https://system.swingfitacademies.com/coaches/my-sessions.php?c=<coach code> (codes held by Max, not published here) |
All flows › Member event
When someone registers for a member event or clinic (Zoho Backstage)
Someone registers for a member event via Backstage; CRM syncs it, sends confirmation and reminder emails, and staff get a daily digest.
- Starts when
- A person completes checkout on an event's Backstage registration widget on events.swingfitacademies.com (or registers directly in the Backstage portal), creating an order + attendee record in Backstage for that event.
- Covers
- Covers a member or guest registering for a SwingFIT group class/clinic via the public Backstage checkout widget on events.swingfitacademies.com, through the CRM sync, confirmation/reminder emails, and the daily staff/coach digest. Does not cover the separate Zoho Creator member-portal pilot path (not live), exhibitor/sponsor/booth features, or GolfManager bay bookings — nothing in this flow touches GolfManager.
- Systems
- Zoho Backstage, Zoho Flow, Zoho CRM, Zoho Cliq, Website (WordPress events.swingfitacademies.com), Zoho Creator (pilot path, not live)
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0checkoutWebsite
Member clicks Register on the events page
From codeEach event card on events.swingfitacademies.com loads Backstage's own embeddable registration widget (one script/CSS load per page, then
window.ZBSCheckOutWidget._createWidget({...})called once per event card with that event's owneventUrl). The widget opens a modal checkout hosted by Backstage, not a SwingFIT page.See itBackstage portal -> Events -> the event -> Registrations tab shows the new order. - T+0ticket classBackstage
Attendee picks a ticket class - free Member or paid Guest
From codeEvery live event carries at least two ticket classes: a free class (often hidden behind an access code/embedded link) for members, and a public paid class for guests. Backstage has no native membership check at checkout - anything gating who can use the free class today is an access code, not an automated CRM lookup.
See itBackstage -> event -> Ticket Classes. - T+0Backstage's own emailBackstage
Backstage sends its own order/ticket confirmation
UnverifiedBackstage's platform automatically emails an order confirmation with the ticket on every completed order - this is native Backstage behavior, separate from anything SwingFIT built in CRM. It is not editable from CRM and (per the 2026-08-19 vendor question list) does not carry a QR code for attendees.
See itNot independently verifiable with the tools available this pass (no attendee-inbox access) - inferred from Backstage's documented order-confirmation behavior and the vendor-question doc. - T+~30ssync to CRMZoho Flow
A portal-wide webhook pushes the new attendee into CRM
Verified liveZoho Flow
Backstage Signup - Event Reminders CRM(link_namebackstage_signup_event_reminders_crm) is a portal-wide webhook trigger (any event, any order). ItsBackstageAttendeeFetchAndSyncstep sends a webhook to CRM functionsfaBackstageAttendeeSync, which creates oneEvent_Remindersrecord (Name, Email, Backstage_Event_ID, Backstage_Attendee_ID, Event_Name, Event_Start, Venue, Coach_Name).- Confirmed on 2 real signups (2026-09-22)Verified live
Confirmed on 2 real signups (2026-09-22): Event_Reminders record 6296422000054081120 created 2026-09-22T12:10:22+04:00 (T+31s), and Event_Reminders record 6296422000054073064 created 2026-09-22T06:51:06+04:00 (T+31s). Both were for 'Group Class - Course Management: Fewer Big Numbers, 23 Sep', with Coach_Name correctly filled in as 'Henry Beischer' on both.
See itCRM -> Event_Reminders module, search by the attendee's email. - T+~30sconfirmation emailZoho CRM
CRM sends its own instant confirmation email
UnverifiedWorkflow rule
Send Instant Confirmation Email(id 6296422000051001762, trigger: Event_Reminders create) fires theInstant Confirmation Emailnotification, which uses template 'Event Confirmation Email' (id 6296422000051130093), from SwingFIT Academies <info@swingfitacademies.com>.- Rule is active and firingVerified live
getWorkflowRuleById shows status.active=true, last_executed_time 2026-09-23T06:59:57+04:00 (today).
See itContact record -> Emails related list, look for 'Event Confirmation Email' with sent=true. - daily 08:00 Asia/Dubaicoach name backfillZoho CRM
A daily sweep fills in any missing coach name
From codeSchedule
sfaCoachNameBackfillSweepscans Event_Reminders for null Coach_Name, looks up the event's Backstage Speaker via thezbackstageconnection, and writes the name back. Deliberately decoupled from the sync above so a Backstage lookup failure here can never block a signup or its confirmation email.See itEvent_Reminders record -> Coach_Name field should never sit null for more than a day. - T-24h before Event_Start24h reminderZoho CRM
A reminder goes out the day before the event
UnverifiedWorkflow rule
Send 24-Hour Event Reminder(id 6296422000051001778) is a date-relative 'once' trigger off Event_Start minus 1 day, criteria Reminder_Sent=false AND Cancelled=false, sending template 'Event Reminder Email' (id 6296422000051130090). Active, last_executed_time 2026-09-22T18:01:25+04:00.- Same-day registrations fall outside the windowFrom code
This is a date-relative 'once' trigger evaluated at Event_Start minus 1 day, at the moment the record is created. If someone registers less than 24 hours before the event, that window has already passed, so this rule is designed to only ever produce the instant confirmation for them.
See itContact -> Emails related list, look for 'Event Reminder Email'. - daily 08:00 Asia/Dubaistaff + coach digestZoho CRM
Staff and coaches get a daily rundown of who's coming
Verified liveSchedule
sfaDailyGuestReport(EV-4 Task 4) queries that day's Event_Reminders, cross-checks each attendee's email against Contacts to flag member vs. guest, emails an HTML digest to max/akash/vic/lucy@swingfitacademies.com, posts the same digest to Cliq channel #Event Updates, and DMs each coach with an event that day viacoachdigestbot.See itThe #Event Updates Cliq channel, or the daily email in the four staff inboxes above.
Emails and messages
CustomerBackstage native order confirmationUnverifiednot captured this pass
CustomerEvent Confirmation EmailUnverifiednot re-opened this pass; last read 2026-08-18
Full text (not found as a file - lives only in CRM Setup > Email Templates (category 'Reminder Automations'); body text above captured from a prior session read, not re-verified this pass)
CustomerEvent Reminder Email (24-hour)UnverifiedReminder: Event_Name is tomorrow!
Full text (not found as a file - lives only in CRM Setup > Email Templates (category 'Reminder Automations'))
TeamDaily Guest ReportVerified liveDaily Guest Report - {date}
Full text (crm_email_templates/flows_bookings/SFA-Functions-PasteSheet.md (function source pasted there, lines ~4534-4589))
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did a member's registration actually reach CRM? | CRM -> Event_Reminders module, search by email | A record exists with the right Event_Name, Venue, Coach_Name and Cancelled=false, created within ~a minute of the Backstage order. |
| Did the confirmation email actually go out? | The Contact record -> Emails related list | An 'Event Confirmation Email' entry, sent=true, from info@swingfitacademies.com, on the Contact's Emails related list, dated close to the registration time. |
| Is today's event list going out to the team? | The four staff inboxes (max/akash/vic/lucy@) or the #Event Updates Cliq channel, around 08:00 Dubai | One digest email/post per day, grouped by event, with member/guest counts matching Backstage's own attendee list. |
| Is a given automation actually live, or was it caught in the 2026-09-09 mass switch-off? | CRM_Automations getWorkflowRuleById on the rule's id | status.active = true and the name has no 'ZZOFF-2026-09' prefix. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| The whole Backstage->CRM sync | Zoho Flow -> Backstage Signup - Event Reminders CRM -> toggle off | No new Event_Reminders record for any new signup, anywhere - confirmation email, 24h reminder and the daily guest report all stop seeing new attendees (existing records keep behaving per their own triggers). |
| Just the instant confirmation email | CRM Setup -> Automation -> Workflow Rules -> Event_Reminders -> Send Instant Confirmation Email -> deactivate | Only the confirmation email; sync, 24h reminder and the guest report are unaffected. |
| Just the 24-hour reminder | Same page -> Send 24-Hour Event Reminder -> deactivate | Only the reminder email. |
| The daily staff/coach digest | CRM Setup -> Automation -> Schedules -> sfaDailyGuestReport -> disable | The staff digest email, the Cliq channel post, and the per-coach Cliq DMs. |
| The coach-name backfill | CRM Setup -> Automation -> Schedules -> sfaCoachNameBackfillSweep -> disable | Only the Coach_Name auto-fill; does not touch any email. |
Good to know
There are two separate registration paths
The live one is the public Backstage checkout widget embedded on events.swingfitacademies.com (WordPress + a custom plugin, no login required). A second path exists in Zoho Creator (a member-only 'Event Registration' form gated on live CRM membership status via function evt_creator_order_gate) - it was built and proven end-to-end in testing but its Flow was switched off as of the last confirmed check; it is a Phase-0 pilot, not the everyday path.
Free vs. paid is a ticket-class split, not a login check
Each event carries a free 'Member' ticket class (typically hidden, unlocked by an access code or embedded link) and a public paid 'Guest' class. Backstage has no native way to check membership status at checkout - nothing today automatically stops someone using a leaked member link, beyond the access code itself.
Member events don't touch GolfManager at all
Registering for a group class or clinic creates no GolfManager booking and consumes no GolfManager credit or bay resource - the whole flow lives in Backstage and CRM, independent of the golf-bay booking system.
Event segmentation isn't live yet
A plan exists (CRM computes 5 fields, ZMA filters on them) but the fields that would drive it - Level_Segment, Member_Tier, Event_Interests - are still under 2% populated. In practice, every event currently goes out however staff choose to promote it, not via an automated segment.
The Fill Engine (EV-4) is only partly built
Of its planned tasks, only the daily guest/coach digest (Task 4, sfaDailyGuestReport) is fully live. The rest of that workstream is open, with one task noted as blocked as of 2026-09-18.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (9)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Backstage checkout widgetn/a (embedded JS widget, window.ZBSCheckOutWidget) | other | Active | member clicks Register on an event card n/a | Loads Backstage's own script/CSS once per page and calls window.ZBSCheckOutWidget._createWidget({...}) per event card with that event's own eventUrl, opening a modal checkout hosted by Backstage rather than a SwingFIT page. | events.swingfitacademies.com (WordPress + custom plugin) n/a (WordPress plugin config, not in the archive) |
Backstage native order/ticket confirmation emailn/a (Backstage platform behavior) | other | Active | order completed none | Automatically emails an order confirmation with the ticket - native Backstage behavior, not editable from CRM or Flow, and per the 2026-08-19 vendor question list does not carry a QR code. | Zoho Backstage platform settings n/a (Backstage platform, no Deluge source) |
Backstage Signup - Event Reminders CRMlink_name backstage_signup_event_reminders_crm | flow | Active last run verified live 20 | Backstage portal-wide webhook, any event, any order (attendee create) none - fires for every attendee on every event | Its BackstageAttendeeFetchAndSync step calls the Backstage API for the attendee, event and speaker details, then sends the assembled payload as a webhook to CRM function sfaBackstageAttendeeSync, which de-dupes on Backstage_Attendee_ID (returns 'duplicate_skipped' if a matching Event_Reminders record already exists) and otherwise creates one Event_Reminders record (Name, Email, Backstage_Event_ID, Backstage_Attendee_ID, Event_Name, Event_Start, Venue, Coach_Name) via zoho.crm.createRecord with the workflow-trigger option set, so downstream create-triggered rules fire. | Zoho Flow > default folder flow_deluge_source/BackstageAttendeeFetchAndSync.deluge (Flow step); crm_deluge_source/sfabackstageattendeesync.deluge (CRM function) |
Send Instant Confirmation Email6296422000051001762 | workflow rule | Active last run 2026-10-11T14:14 | create none | Fires the 'Instant Confirmation Email' notification action, sending template 'Event Confirmation Email' (id 6296422000051130093) from SwingFIT Academies <info@swingfitacademies.com>. | Zoho CRM > Setup > Automation > Workflow Rules > module Event_Reminders email_notifications action only, no custom Deluge function |
Send 24-Hour Event Reminder6296422000051001778 | workflow rule | Active last run 2026-10-10T10:00 | date_or_datetime (date-relative 'once', evaluated at Event_Start minus 1 day, at record-create time) Reminder_Sent equals false AND Cancelled equals false | Fires the '24-Hour Reminder Email' notification action, sending template 'Event Reminder Email' (id 6296422000051130090). Because the trigger window is evaluated once at create time, a same-day registrant (event less than 24h away) never gets this reminder - only the instant confirmation. | Zoho CRM > Setup > Automation > Workflow Rules > module Event_Reminders email_notifications action only, no custom Deluge function |
sfaCoachNameBackfillSweep6296422000051779009 (schedule id; function id 1446733000000762003) | schedule | Active last run 2026-09-02T08:04 | daily 08:00 Asia/Dubai Event_Reminders where Coach_Name is null | Looks up the event's Backstage Speaker via the zbackstage connection and writes the coach name back onto the Event_Reminders record. Deliberately decoupled from the real-time sync so a Backstage lookup failure here can never block a signup or its confirmation email. | Zoho CRM > Setup > Automation > Schedules crm_deluge_source/sfacoachnamebackfillsweep.deluge |
sfaDailyGuestReport6296422000051579026 (schedule id; function id 1446733000000762001) | schedule | Active last run 2026-09-02T08:04 | daily 08:00 Asia/Dubai that day's Event_Reminders records | Cross-checks each attendee's email against Contacts to flag member vs. guest, builds an HTML digest grouped by event, sends it (org_email:true set) to max/akash/vic/lucy@swingfitacademies.com, posts the same digest text to Cliq channel #Event Updates, and DMs each coach with an event that day via coachdigestbot. | Zoho CRM > Setup > Automation > Schedules crm_email_templates/flows_bookings/SFA-Functions-PasteSheet.md (source pasted there); function api_name sfadailyguestreport |
EVT Creator Order Gate - TEST (Phase 0) / function evt_creator_order_gatelink_name evt_creator_order_gate_test_phase_0 | flow | Inactive | n/a - disabled checks whether the member's email has an active (status live or non_renewing) Membership before allowing the free ticket class | The one built enforcement mechanism for membership-gated free tickets - wired to the separate Zoho Creator 'Event Registration' pilot form, not to the real events.swingfitacademies.com Backstage widget used in this trace. | Zoho Flow > default folder (pilot) flow_deluge_source/evt_creator_order_gate.deluge |
ZBookings - Metalink_name zohobookingseventbooking_meta_capi | flow | Inactive | n/a - disabled n/a | Appears to belong to the separate Zoho Bookings system (lesson bookings), not Backstage member events - orphaned/out-of-scope debris for this flow. | Zoho Flow > folder 'Zoho - Meta' n/a (Meta CAPI webhook step, no custom function found) |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Event_Reminders | Name, Email, Backstage_Event_ID, Backstage_Attendee_ID, Event_Name, Event_Start, Venue | Core attendee/event record synced from Backstage | sfaBackstageAttendeeSync |
| Event_Reminders | Coach_Name | Name of the event's Backstage Speaker; filled at sync time when available, or backfilled the next morning if null | sfaBackstageAttendeeSync (at sync) / sfaCoachNameBackfillSweep (backfill) |
| Event_Reminders | Cancelled | Set when a Backstage registration is cancelled; the 24h reminder rule filters on this being false | not confirmed this pass - likely a Backstage cancel-sync path (schedule 'Backstage Attendee Cancel Sync' / function sfaBackstageAttendeeCancelSync, seen in schedules_live.tsv but not traced in this pass) |
| Event_Reminders | Reminder_Sent | Guards the 24-hour reminder rule from re-firing | written natively by the workflow rule's own notification action, not a custom function |
IDs and references
| What | Value |
|---|---|
| CRM workflow rule — Send Instant Confirmation Email | 6296422000051001762 |
| CRM email template — Event Confirmation Email | 6296422000051130093 |
| CRM workflow rule — Send 24-Hour Event Reminder | 6296422000051001778 |
| CRM email template — Event Reminder Email | 6296422000051130090 |
| CRM schedule — sfaCoachNameBackfillSweep | 6296422000051779009 |
| CRM schedule — sfaDailyGuestReport | 6296422000051579026 |
| Cliq channel — daily digest | #Event Updates |
| Cliq bot — coach DMs | coachdigestbot |
All flows › Coach Area
How a coach sees their own day, sessions and numbers (Coach Area)
Coaches open one tab inside Zoho CRM that shows only their own sessions, group classes, reports, pay numbers and Analytics dashboard.
- Starts when
- A coach (or the admin) opens the Coach Area tab in Zoho CRM.
- Covers
- The 'Coach Area' Web Tab in Zoho CRM used by the four coaches, with a 'View as' picker for the admin. Covers what each tab shows, where the data comes from and who can see what. Does not cover how pay is agreed or the Analytics dashboards' own build.
- Systems
- Zoho CRM, Zoho Analytics
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- On openOpen tabZoho CRM
The page identifies who is looking
Verified liveThe page is hosted at system.swingfitacademies.com/coaches/area.html and loaded inside CRM. It never decides who the user is: it passes the signed-in CRM user's email to one CRM function, which maps it to a coach (Harry, Henry, Stian, Pradeep). Anyone not on the list gets a no-access message. The admin also gets a 'View as' picker for the four coaches.
See itOpen the tab as the admin and switch the picker; the title and all tabs follow the chosen coach. - First tabMy day todayZoho CRM
My day today
Verified liveShows this month's report box (logged, complete, still missing, with links to the Lesson Report and Evaluation Debrief forms), then today's lessons, evaluations and group classes in time order.
See itCompare with the coach's CRM bookings for today. - Second tabUpcomingZoho CRM
Upcoming (next 7 days)
Verified liveLessons, evaluations and group classes from tomorrow for 7 days, merged by day. Lessons show recent history; evaluations show whether the intake form is done. Group classes come from the member-event reminders and show the signed-up players (capacity 4). A class with zero sign-ups does not appear.
See itCompare with Bookings, Evaluation_Booking and Event_Reminders for the coach. - Third tabPastZoho CRM
My past sessions
Verified livePast sessions with the report status for each, so a coach can see what is still missing.
See itA session with a Lesson Report shows as logged. - Fourth tabNumbersZoho Analytics
My numbers
Verified liveEffective lessons, band and pay for the month, read from the 'Coach's monthly commission' table in Zoho Analytics and filtered to that one coach. Pay text differs by contract: the PGA coaches use the bands, the junior coach is on the junior rate, and one coach is on the older contract (base, plus a per-lesson rate above 140 lessons, plus a share of PAYG revenue he created that month).
See itCompare the figures with the Analytics table row for that coach and month. - Fifth tabDeeper diveZoho Analytics
Deeper dive (own Analytics dashboard)
Verified liveEmbeds the coach's own Analytics dashboard in the page, with an 'Open in a new tab' button as fallback. The CRM function returns only that coach's link (the admin gets all four). The coach must also have view-only access to their dashboard in Analytics, otherwise the box shows a sign-in page.
See itEach coach opened the tab and saw only their own dashboard (tested with the full coach team, 2026-10-09 or later). - OngoingSpeedZoho CRM
Short-term cache
Verified liveThe page keeps results in the browser for a few minutes (sessions and upcoming 5 min, reports and numbers 15 min) to limit CRM calls. A Refresh link clears it.
See itRefresh link at top right.
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Is a coach seeing only their own data? | Sign in as that coach (or use 'View as' as admin) and check the name in the title and the data on each tab. | Only that coach's sessions, classes, numbers and dashboard appear. |
| Why is a number missing? | Zoho Analytics, 'Coach's monthly commission' table. | The row for that coach and month exists. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| The whole Coach Area | CRM Setup, Developer Hub, Widgets / Web Tabs: remove the tab from the coaches' profile. | Coaches lose the page; nothing else in CRM changes. |
| Dashboard embeds | Remove an entry from the function's embed list. | That coach's Deeper dive shows 'not set up yet'. |
Good to know
Read-only
The function only reads data. Nothing is sent or changed in CRM.
Group class gap
Group classes with no sign-ups do not show, because they are found through the sign-up reminders.
Sharing is separate
The page limits what a coach sees, but access to the Analytics dashboard itself is a separate permission in Analytics (view-only, own dashboard).
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (3)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
sfaCoachArea | function | Active | Called by the widget via ZOHO.CRM.FUNCTIONS.execute(action, coach, job, who) who (CRM user email) must be in the roster harry|henry|stian|pradeep @swingfitacademies.com or the admin list (max@). Non-admins can only get their own coach. | Actions: whoami, me (name, key, admin, coaches, embeds), sessions, upcoming (7 days: Bookings, Evaluation_Booking, Lesson_Reports, Event_Reminders via COQL), numbers and reports (Analytics bulk async export, filtered to one coach in the function). Read-only. | CRM Setup, Functions (standalone). Needs REST API and OAuth2 toggles on; connections crm_info and analytics_read. domains/coaching/coach-area/sfaCoachArea-2026-10-08.deluge |
Coach Area Web Tab | widget | Active | Tab opened in CRM Uses SDK live.zwidgets.com/js-sdk/1.2; page is noindex; no data held on the page | Renders five tabs, the View-as picker (admin), browser cache with TTL sessions/upcoming 5 min and reports/numbers 15 min, and the dashboard iframe (URL strictly checked against analytics.zoho.*/open-view/<id>). | CRM Web Tab widget, external hosting site/coaches/area.html (source: coach-area-crm/area.html); live v12, sha 16e4b48953b1ef2d |
Site auto-deploy | deploy | Active last run 2026-10-09 (comm | Push to main Takes about 1 to 2 minutes | Publishes coaches/area.html. Push with scripts/push.py. | GitHub repo swingfitacademies/system.swingfit, site/** to Hostinger by SFTP scripts/push.py |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Event_Reminders (CRM) | Coach_Name | Used to find a coach's group classes; cancelled ones are filtered out. | member-event flow |
| Analytics: Coach's monthly commission | Coach, Band, effective lessons, pay | Source for My numbers. No PAYG Revenue column yet. | Analytics owner |
IDs and references
| What | Value |
|---|---|
| Analytics workspace | 2930939000002155003 |
| Analytics org | 866470307 |
| Dashboard view ids (harry / henry / pradeep / stian) | 2930939000007674852 / 2930939000010684012 / 2930939000007674527 / 2930939000007666620 |
| Function entity ID | not captured (saved in CRM UI); capture if recreated |
All flows › PAYG follow-ups
After a PAYG purchase: the nurture and credit-reminder emails
After a PAYG pack purchase, daily CRM sweeps check usage and credit balance to send booking nudges, top-up offers, and re-engagement emails.
- Starts when
- A PAYG pack purchase sets Contacts.Paygon_Stage=1 (via
sfaPaygonWelcome, Day 0 - covered separately). From that point, three independent daily sweeps and one date-based rule run against the whole PAYG book, keyed off days-since-purchase, credit balance, and credit expiry date - nothing further is triggered by the purchase event itself. - Covers
- What happens to a PAYG (pay-as-you-go pack) buyer in the days and weeks after purchase: the Day-3/Day-7 check-in sweep, the low-balance/expiry credit-upsell sweep, the lapsed-buyer winback sequence, and where membership upsell and per-lesson emails sit alongside it. Does not cover the Day-0 welcome email itself (covered separately) or the purchase/checkout flow.
- Systems
- Zoho CRM
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- daily 14:00Day 3 after purchaseZoho CRM
Day-3 check-in: booked vs. not booked
UnverifiedsfaPaygonSweep(schedule, daily 2pm) scans every contact at Paygon_Stage=1. Once 3+ days have passed since Paygon_First_Purchase_Date, it checks the contact's Bookings for a matching upcoming/recent session against the pack type they bought (coaching, bay/practice, fitness or junior). Sends PAYGON-2a if a matching booking exists, PAYGON-2b if not, and advances Paygon_Stage to 2 either way.See itCRM → Contacts → Paygon_Stage field, plus the contact's Emails related list. - daily 14:00Day 7 after purchaseZoho CRM
Day-7 check-in: well-used vs. barely used
UnverifiedThe same
sfaPaygonSweeprun also scans contacts at Paygon_Stage=2. Once 7+ days have passed since first purchase, it counts matching sessions taken since purchase. 2 or more sessions sends PAYGON-3a (momentum framing); fewer sends PAYGON-3b (expiry-reminder framing). Advances Paygon_Stage to 3 either way — this is the last stage the sweep ever sets.See itCRM → Contacts → Paygon_Stage field, plus the contact's Emails related list. - daily 11:00ongoing, whole PAYG bookZoho CRM
Credit Upsell sweep (CREDITUP) — low balance or expiry, plus usage check
Verified livesfacreditup("Credit Upsell Automation") scans every Client-lifecycle (PAYG, non-member) contact daily across all 4 credit types. A type qualifies if its balance is 1 credit or its expiry is within 14 days AND the contact used that credit type 2+ times in the trailing 60 days (protects against pitching someone who's gone quiet). Sends CR-TOPUP normally, or CR-MEMBERSHIP instead if usage was 8+ sessions in 60 days (roughly weekly) — a membership pitch, not a top-up nudge. Composes the subject/body per credit type into CreditUp_Subject/CreditUp_Body fields that the template merges in.- CooldownsFrom code
Won't re-touch a contact within 14 days of its own last send (Last_CreditUp_Touch), or within 4 days of any other nurture send (Last_Nurture_Sent). A membership pitch specifically won't repeat within 30 days (Membership_Pitch_Last_Touch).
See itCRM → Contacts → Last_CreditUp_Touch, CreditUp_Subject/Body fields, plus the Emails related list. - daily 20:04from halfway through a packZoho CRM
Pack expiry reminders: halfway and 10 days before expiry
Verified livesfaB6Sweep(daily schedule) reads every 4, 8 and 12-pack with sessions left and emails the buyer twice: once halfway through the pack's validity (4-packs about 30 days before expiry, 8-packs and 12-pack Beginner/Practice about 60 days before, other 12-packs about 90 days before) and again 10 days before expiry. If several packs are due on the same day they go in one email, listing sessions left and the use-by date for each. Booked sessions are already taken off the balance, so the email counts only sessions still to book. Skips members (they get the member reminders below) and anyone who already got another nurture email that day. Uses its own template with a non-member footer.- Member credit reminders (same function)Verified livedaily 20:04
The same run first reminds Customer_Type=Member contacts about their member credits, each type with its own timing (Member Lesson 28/15/10 days before expiry, Member Coaching 180/60/30/10, Regular Coaching, Practice, Fitness and Junior 60/30), skipping members who already have a matching session booked this month.
See itCRM → Contacts → B6_Touches_Sent (codes starting PH- or PT10-), Last_Nurture_Sent, plus the Emails related list. - date-based, once, 60 days after Last_Activity_Datelapsed PAYG buyerZoho CRM
Lapsed PAYG winback (B8 Branch P)
UnverifiedA separate workflow rule (not a daily sweep) fires once per contact, 60 days after their Last_Activity_Date, for any non-member, non-churned lifecycle contact who hasn't already had a winback started. It's a 3-part sequence: instant "B8 P1 – Lapsed Check-In", +7 days "B8 P2 – Cost of Not Practising", +21 days "B8 P3 – Free Evaluation Invite" — this is the only automation that re-engages a PAYG buyer who's gone quiet rather than just reminding them their credits are running out.
See itCRM → Setup → Automation → Workflow Rules → search "Lapsed PAYG Winback"; contact field Winback_Started. - on lesson report saveany time during the packZoho CRM
Post-lesson progress note (T3)
Verified liveT3 Post-Lesson Progressfires whenever a coach saves a Lesson_Reports record, regardless of whether the player is a PAYG buyer or a member. It's not part of the credit-nurture cadence, but it's a touchpoint that can land inside the same Day 0–21 window, so staff should know it exists alongside the sweeps above.See itCRM → Setup → Automation → Workflow Rules → "T3 Post-Lesson Progress". - on Practice Pass create / 2 days before endPractice Pass product onlyZoho CRM
Practice Pass confirmation, reminder and upsell
Verified liveA separate 3-rule set —
Practice Pass Confirmation,Practice Pass Two Days Out,Practice Pass Upsell— runs against the Practice_Passes module, which is a distinct product from the PAYG credit packs this trace covers. Mentioned here because staff sometimes conflate the two: a "Practice Pass" is not the same record as a Practice_Credit_Balance pack.See itCRM → Setup → Automation → Workflow Rules → filter "Practice Pass".
Emails and messages
CustomerPAYGON-2a — You're booked in.UnverifiedYou're booked in.
Full text ($HOME/mnt/SwingFIT AI OS/crm_email_templates/flows/PAYGON-Copy-Station.html (subject/preheader extracted; full HTML body not pulled in this pass))
CustomerPAYGON-2b — Your pack is waiting.UnverifiedYour pack is waiting.
Full text ($HOME/mnt/SwingFIT AI OS/crm_email_templates/flows/PAYGON-Copy-Station.html)
CustomerPAYGON-3a — You're building momentum.UnverifiedYou're building momentum.
Full text ($HOME/mnt/SwingFIT AI OS/crm_email_templates/flows/PAYGON-Copy-Station.html)
CustomerPAYGON-3b — Don't let this expire unused.UnverifiedDon't let this expire unused.
Full text ($HOME/mnt/SwingFIT AI OS/crm_email_templates/flows/PAYGON-Copy-Station.html)
CustomerCR-TOPUPVerified liveYour credit type credit(s) is/are almost gone (e.g. "Your practice credits are almost gone")
CustomerCR-MEMBERSHIPVerified liveYou're in almost every week. Membership pays off better.
CustomerB6 member credit reminders (4 variants: new/expiring x booked/not-booked)UnverifiedYour credit type Credit Expires Soon / Your credit type Credit Just Landed
CustomerB8 P1/P2/P3 — Lapsed PAYG winback sequenceUnverifiedP1: lapsed check-in · P2: cost-of-not-practising angle · P3: free evaluation invite
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did a PAYG buyer get their Day-3/Day-7 check-in? | Contacts → Paygon_Stage field (should read 2 after Day 3, 3 after Day 7) and the contact's Emails related list. | Paygon_Stage has moved past 1, and a PAYGON-2a/2b or 3a/3b email shows in Emails with a real send time. |
| Why hasn't a low-balance/top-up email gone out to a PAYG buyer? | Contacts → Last_CreditUp_Touch and CreditUp_Subject fields; CRM Setup → Automation → Schedules → "Credit Upsell Automation" for its enabled/last-run status. | Last_CreditUp_Touch is recent (within the last couple of weeks) for a contact with a low/expiring balance and 2+ recent sessions. |
| Why hasn't a member's credit-expiry reminder arrived? | Contacts → B6_Subject/B6_Touches_Sent fields (should update on schedule) vs. the Emails related list (should show a matching send). | Both the field stamp and a matching Emails record exist for the same date. |
| Is a PAYG buyer who's gone quiet getting followed up with? | CRM Setup → Automation → Workflow Rules → search "Lapsed PAYG Winback"; check status.active. | Rule shows active:true, with recent activity in the contact's Emails related list. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Day-3/Day-7 PAYG check-in emails and Paygon_Stage progression | CRM Setup → Automation → Schedules → disable "sfaPaygonSweep" | Stops the Day-3 booked/not-booked and Day-7 well-used/barely-used emails and the Paygon_Stage field updates. |
| PAYG low-balance/expiry/membership-pitch emails | CRM Setup → Automation → Schedules → disable "Credit Upsell Automation" (sfacreditup) | Stops CR-TOPUP and CR-MEMBERSHIP sends and the Last_CreditUp_Touch/CreditUp_Subject field updates for PAYG (non-member) contacts. |
| Member credit-expiry reminders | CRM Setup → Automation → Schedules → disable "sfaB6Sweep_Daily" | Stops the B6 field stamps for members. |
| Lapsed PAYG winback sequence | Already off — CRM Setup → Automation → Workflow Rules → "ZZOFF-2026-09 B8 Branch P - Lapsed PAYG Winback", status inactive | Already stopped since 2026-09-09. |
Good to know
Paygon_Stage is the whole state machine
1 = welcomed (Day 0), 2 = Day-3 check-in sent, 3 = Day-7 check-in sent. There is no stage 4+ — once a PAYG buyer reaches stage 3, the sweep never touches them again; any further contact comes only from CREDITUP (balance-driven) or the B8 winback rule (inactivity-driven).
CREDITUP and B6 are parallel systems, PAYG vs. Member
sfacreditup covers PAYG (Lifecycle_Status=Client) contacts across 4 credit types (coaching, practice, fitness, junior); sfaB6Sweep covers Members (Customer_Type=Member) across 6 credit types with more granular per-type offsets. They use different Contact fields and different templates, and neither one covers the other's audience.
CREDITUP's usage gate
A qualifying low/expiring balance only triggers a send if the contact used that credit type 2+ times in the trailing 60 days — someone who bought a pack and never came back gets no upsell email, by design. 8+ sessions in 60 days routes to the membership pitch instead of a top-up nudge.
Practice Pass ≠ PAYG credit pack
"Practice Pass" is a separate CRM module (Practice_Passes) with its own confirmation/reminder/upsell rules. A contact's Practice_Credit_Balance (part of the PAYG pack this trace covers) is a different record from a Practice Pass.
Known upsell coverage gap, already tracked
CREDITUP only reaches PAYG non-members; Practice/Unlimited/Junior/Founder members and PAYG "buy" customers have no equivalent upsell path today. Max flagged this 2026-09-21 (state/progress.md "Upsell coverage gap" card); it's queued but not yet scoped or built.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (6)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
sfaPaygonSweepschedule 6296422000046337508 / function id 1446733000000645004 | schedule | Off last run unknown (schedul | daily 14:00 Stage-1 pass: zoho.crm.searchRecords("Contacts","(Paygon_Stage:equals:1)"), days since Paygon_First_Purchase_Date >= 3, checks Bookings for a matching session. Stage-2 pass: same search on Paygon_Stage=2, days>=7, counts sessions since purchase (>=2 = well-used). | Calls function sfaPaygonSweep. Sends PAYGON-2a (booked, template 6296422000046337587) or PAYGON-2b (not booked, 6296422000046337590) at Day 3, advancing Paygon_Stage to 2; sends PAYGON-3a (well-used, 6296422000046337593) or PAYGON-3b (barely-used, 6296422000046337596) at Day 7, advancing Paygon_Stage to 3. Sends via crm/v8/Contacts/{id}/actions/send_mail. | CRM › Setup › Automation › Schedules crm_functions_live/functions/sfaPaygonSweep.deluge |
Credit Upsell Automation (sfacreditup / CREDITUP)schedule 6296422000046337444 / function id 1446733000000651001 | schedule | Code last run unknown (schedul | daily 11:00 Scans Contacts where Lifecycle_Status=Client, paged 200 at a time, across 4 credit types (coaching/practice/fitness/junior). A type qualifies if balance<=1 or expiry within 14 days, AND usage>=2 sessions in the trailing 60 days (via a Bookings search per contact). 8+ sessions in 60 days routes to the membership pitch instead. Cooldowns: 14 days since Last_CreditUp_Touch (own), 4 days since Last_Nurture_Sent (any nurture), 30 days since Membership_Pitch_Last_Touch. | Calls function sfacreditup. Sends CR-TOPUP (template 6296422000046337433) or CR-MEMBERSHIP (6296422000046337436) via crm/v8/Contacts/{id}/actions/send_mail, WITH org_email:true set on the payload (one of the few functions in this whole codebase seen to include it) — consistent with the raw trace tagging these sends "verified". | CRM › Setup › Automation › Schedules $HOME/arch/crm_deluge_source/sfacreditup.deluge |
sfaB6Sweep_Daily (sfaB6Sweep)schedule 6296422000049047003 / function id 1446733000000701007 | schedule | Active last run 2026-10-01 11:42 | daily 20:04 Dubai Pass 1: Customer_Type=Member, 6 credit types from Contact rollup fields (unchanged). Pass 2: every Credits record named "4 x", "8 x" or "12 x" with Balance > 0 and Expiry_Date >= today, read via v8 COQL (invokeurl, connection crm_info); skips contacts with Customer_Type=Member, Full_Name containing "ignore", no email, or Last_Nurture_Sent = today. | Calls function sfaB6Sweep daily for Customer_Type=Member contacts across 6 credit types, each with its own reminder offsets before expiry (Member Lesson 28/15/10 days; Member Coaching 180/60/30/10 days - the 10-day touch covers monthly Beginner credits, which are held in the Member Coaching fields; Regular Coaching, Practice, Fitness, Junior 60/30). Skips members with a matching upcoming booking. Writes the B6_* merge fields, sends one of 4 templates (6296422000048862719/722/725/728) from info@ via crm/v8 Contacts send_mail with org_email, and records the touch in B6_Touches_Sent only after a confirmed send (a failed send retries next run). One summary alert to max@ per run if any send fails. PASS 2 (v3, 2026-09-30; v3.1 2026-10-01): PAYG pack reminders. Validity = min(actual Created_Time-to-Expiry_Date span, nominal: 4x=60d, 8x=120d, 12x Beginner/Practice=120d, other 12x=180d). Touch H fires when days-to-expiry is within [half-2, half] (only if half >= 18); touch PT10 within [8, 10]. All due packs per contact go in one email via template CR-PAYG-EXPIRE-NOTBOOKED 6296422000055135003 (copy of ...725 with non-member footer), from info@ with org_email. On SUCCESS stamps B6_Touches_Sent (PH-<creditId> / PT10-<creditId>) and Last_Nurture_Sent = today (sfacreditup honours a 4-day guard on it). Failed sends retry next run and are included in the max@ alert; a failed Credits query also alerts. History: before 2026-09-30 the send lacked org_email (nothing delivered from early Aug); v3 pass 2 used zoho.crm.searchRecords, which rejects greater_than on Credits, so it sent nothing on 2026-09-30; fixed in v3.1. | CRM › Setup › Automation › Schedules crm_functions_live/functions/sfaB6Sweep.deluge |
B8 Branch P - Lapsed PAYG Winback6296422000045654103 | workflow rule | Inactive last run 2026-09-09T15:00 | Contacts, date-based: Last_Activity_Date + 60 days, once Non-member, non-churned lifecycle, Winback_Started not already set | 3-part sequence: instant B8 P1, +7 days B8 P2, +21 days B8 P3 (email_notification ids 6296422000045678113 / 6296422000045677108 / 6296422000045675100). | CRM › Setup › Automation › Workflow Rules › module Contacts no separate .deluge function found; appears to be a pure workflow-rule email action |
T3 Post-Lesson Progress6296422000046774054 | workflow rule | Active last run 2026-10-11T19:55 | Lesson_Reports, create or edit Fires on every lesson report save regardless of PAYG/member status | Sends a post-lesson progress note; not part of the credit-nurture cadence but can land in the same Day 0-21 window. | CRM › Setup › Automation › Workflow Rules › module Lesson_Reports n/a (not read in this pass) |
Practice Pass Confirmation / Two Days Out / Upsell6296422000049084117 / 6296422000049055176 / 6296422000049109114 | workflow rule | Active last run 2026-07-30T08:59 | create / End_Date-2 days / create with Pass_Number>=2 See pos-sale trace — Practice_Passes is a separate module/product from the PAYG credit packs this trace covers | Confirmation, reminder and upsell emails on the Practice Pass product. | CRM › Setup › Automation › Workflow Rules › module Practice_Passes $HOME/arch/crm_deluge_source/practicepasssendconfirmation.deluge, practicepasssendtwodaysout.deluge, practicepasssendupsell.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Contacts | Paygon_Stage | 0/blank=never welcomed, 1=Day-0 welcomed, 2=Day-3 sent, 3=Day-7 sent (terminal — sweep never advances past 3) | sfaPaygonWelcome sets 1; sfaPaygonSweep is designed to advance 1→2 and 2→3 (see fix_additions for why this does not happen in practice) |
| Contacts | Paygon_First_Purchase_Date | Anchors the Day-3/Day-7 offset calculation | sfaPaygonWelcome |
| Contacts | Last_CreditUp_Touch, CreditUp_Subject, CreditUp_Body | Cooldown stamp and composed per-send copy for the CREDITUP sweep | sfacreditup |
| Contacts | Membership_Pitch_Last_Touch | 30-day cooldown specifically for the CR-MEMBERSHIP pitch variant | sfacreditup |
| Contacts | Last_Nurture_Sent | Shared 4-day cooldown checked by multiple nurture rules (CREDITUP, RENEW R-3) to avoid stacking sends | multiple functions |
| Contacts | B6_Subject, B6_Touches_Sent | Per-credit-type touch tracking for the member-side sfaB6Sweep | sfaB6Sweep |
| Contacts | Winback_Started | Marks a contact as already in the B8 lapsed-winback sequence | B8 Branch P workflow rule (currently inactive) |
| Contacts | B6_Touches_Sent | Log of reminder touches already sent. Member codes CT<n>T<n>-<expiry>; PAYG codes PH-<creditId> (halfway) and PT10-<creditId> (10 days) | sfaB6Sweep, only after a successful send |
| Contacts | Last_Nurture_Sent | Date of the last nurture email of any kind; sfacreditup skips contacts within 4 days of it, sfaB6Sweep PAYG skips same-day | sfacreditup, sfaB6Sweep (PAYG pass) |
Full email text
CR-TOPUPYour credit type credit(s) is/are almost gone
CR-MEMBERSHIPYou're in almost every week. Membership pays off better.
B6 member credit reminders (4 variants)Your credit type Credit Expires Soon / Your credit type Credit Just Landed
B8 P1/P2/P3 — Lapsed PAYG winbackP1: lapsed check-in · P2: cost-of-not-practising angle · P3: free evaluation invite
PAYG pack expiry reminders (halfway / 10 days)You're Halfway Through Your Pack / Your Sessions Expire Soon
IDs and references
| What | Value |
|---|---|
| Schedule, sfaPaygonSweep | 6296422000046337508 (daily 14:00) |
| Schedule, Credit Upsell Automation | 6296422000046337444 (daily 11:00) |
| Schedule, sfaB6Sweep_Daily | 6296422000049047003 (daily 20:00) |
| Rule, B8 Branch P Lapsed PAYG Winback | 6296422000045654103 (inactive) |
| Rule, T3 Post-Lesson Progress | 6296422000046774054 (active) |
| Template, CR-PAYG-EXPIRE-NOTBOOKED (PAYG pack reminders) | 6296422000055135003 (Contacts, Internal folder) |
All flows › Monthly renewal
When a membership renews each month (and credits top up)
Each month a member's card is charged automatically, creating a renewal invoice and topping up their GolfManager lesson credit and CRM record.
- Starts when
- A member's Zoho Billing subscription hits its recurring billing date and autobill charges the saved card, which creates a matching renewal invoice in Zoho Books (org-specific: Studio City 866469739 or DIFC 872210045), tagged transaction_type="renewal" and sales_channel="direct_sales".
- Covers
- Covers the automatic monthly membership renewal at both SwingFIT orgs (Studio City + DIFC): the Zoho Billing autobill charge, the Books renewal invoice, the Flow-triggered credit top-up into GolfManager and CRM Credits, the Contact balance roll-up, the pre-renewal reminder email, and the receipt/reminder emails around it. Stops at successful payment — a failed renewal charge is a separate flow (dunning: PD-1/2/3, T14 Payment Failed, Dunning_Stage).
- Systems
- Zoho Billing, Zoho Books, Zoho Flow, Zoho CRM, GolfManager
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0 (e.g. 06:00–06:20 Dubai)Autobill charge & invoice createdZoho Billing
Subscription autobill fires, Books invoice is created and charged
Verified liveZoho Billing charges the member's saved card on their subscription's renewal date and syncs a matching invoice into Zoho Books for that member's org. The invoice carries transaction_type: "renewal", sales_channel: "direct_sales", autobill_status: "live", and a cf_golfmanager_membership_id custom field pointing at the GolfManager membership record. DIFC's batch runs first (~06:00–06:05), Studio City's a little later (~06:17–06:18).
- Invoice emailed to the customerVerified liveT+0
Books marks is_emailed: true on the invoice at creation — some invoice/receipt email goes out from Billing's own transactional stack at this point.
See itZoho Books → Invoices (correct org) → filter by today's date; payment_made = total and last_payment_date = today means it charged successfully. - T+0 to T+5sFlow picks up the new invoiceZoho Flow
Flow "ZBilling-ZCRM_INV_CREATION" fires the credit top-up function
From codeA webhook-triggered Zoho Flow (folder "Zoho Billing - Zoho CRM", link name zohobilling_zohocrm) reacts to the new Books/Billing invoice and calls the Deluge function UpdateMembershipCredits_CRM_SubscriptionInv(invoice_id, org_id). This flow's own configuration can't be opened in the Zoho Flow UI (one of 29 flows the platform will not render), so its trigger wiring is read from the function's recorded flow mapping, not from the flow graph itself.
See itZoho Flow → flow "ZBilling-ZCRM_INV_CREATION" is listed as On; function history for UpdateMembershipCredits_CRM_SubscriptionInv shows a run at the invoice's timestamp. - T+~3–4 min (e.g. 06:21:13–06:21:18)Credit top-up runsZoho Flow
UpdateMembershipCredits_CRM_SubscriptionInv works out what credit the plan is owed
Verified liveThe function re-fetches the invoice from Books, matches the Books contact to a CRM Contact by email, then reads the Zoho Billing subscription's plan and its custom field (cf_gm_membership_type_id at Studio City, cf_gm_membership_type_id_1 at DIFC) to get a numeric plan code. A hardcoded lookup table turns that code into a credit name, GolfManager credit-type ID, balance and price (e.g. plan code 9 → "Monthly Member Golf Lesson Credit", GM type 254, balance 1, price 0, 30-day expiry). If no Contact or no matching plan code is found, the function skips that invoice.
See itFunction execution log for UpdateMembershipCredits_CRM_SubscriptionInv around the invoice timestamp. - same runGolfManager voucher rechargedGolfManager
The member's credit voucher is topped up in GolfManager
Verified liveThe function finds (or creates) the matching GolfManager customer by email, then POSTs to GolfManager's voucher recharge endpoint, creating a new voucher of the mapped credit type with the calculated balance, price and expiry date. This is the actual "credit top-up" members use to book lessons.
See itGolfManager → Customers → member → Vouchers tab: a new voucher dated today with the plan's credit type and an end date ~1 month out. - same runCRM Credits record createdZoho CRM
A matching Credits record is written in CRM
Verified liveThe function creates one record in the CRM Credits module (Name, Balance, Player lookup, Expiry_Date, Price_per_Credit, Total_Price, GM_Credit_Type_ID, Reference_ID) mirroring the voucher just created in GolfManager.
See itCRM → Credits module, filter Player = the member, sort by Created Time. - same secondContact balance rolls upZoho CRM
The new Credit is rolled up onto the member's Contact record
Verified liveLive CRM workflow rule "GM Sync - Credits to Contact EngineA" (Credits module, create/edit trigger, active) fires function syncContactCredits, which updates the Contact's running balance fields (e.g. Member_Lesson_Credit_Balance, Credit_Balance, Credit_Expiry_Date) so the front-of-house and member-facing views show the fresh balance without opening the Credits module.
See itContact record → the relevant _Credit_Balance field and Credit_Expiry_Date; Contact's Modified/Last Activity time should match the Credit's Created Time almost exactly. - daily 2am-ish sweepCredit-expiry reminder (pointer)Zoho CRM
A separate daily sweep reminds members before an unused credit expires
From codeThe sfaB6Sweep daily schedule checks each member's Credit_Expiry_Date and sends a "your credit expires soon" nudge if they haven't booked. This is a distinct, already-documented flow — not detailed further here.
See itSee the sfaB6Sweep trace / SW-8 tracker entry for that flow. - T-7 days (before Package_Expiry_Date)7-day renewal reminderZoho CRM
Members get a heads-up email 7 days before their renewal date
Verified liveDate-based CRM workflow rule "RENEW R-3 — 7-Day Renewal Reminder" (Contacts, active, fires at Package_Expiry_Date - 7 days) checks the member is an active Lifecycle_Status (Member/6 Month Member/Beginner Member/Junior Member), on a Monthly Subscription_Interval, not mid-onboarding, not already nurtured in the last 4 days, not cancelling at term end (Renewal_Cancelled, set nightly from Billing since 2026-10-14), and not stuck in the "Needs Card Update" dunning stage. If all pass, it sends the "E-3 Email One Week Renewing" template and stamps Last_Nurture_Sent via a function.
See itContact record -> Emails list shows "Your next membership payment in 7 days" sent ~00:01, and Last_Nurture_Sent is stamped the same day. Rule: Setup -> Automation -> Workflow Rules -> Contacts -> "RENEW R-3 - 7-Day Renewal Reminder".
Emails and messages
CustomerRENEW R-3 — 7-Day Renewal ReminderUnverifiedYour next payment: Players.Membership Expiry Date
CustomerRenewal invoice / autobill charge noticeUnverifiedInvoice from SwingFIT Academies — invoice number
CustomerPayment receiptUnverifiedPayment confirmed
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did a member's renewal actually process today? | Zoho Books → Invoices (correct org) → filter by today's date, look for transaction_type "renewal" | autobill_status "live", payment_made equals total, last_payment_date is today |
| Did their GolfManager credit top up? | GolfManager → Customer (search by email) → Vouchers tab | a new voucher dated today with the plan's credit type and an end date about a month out |
| Where's the CRM record of the credit? | CRM → Credits module, filter Player = the member, sort by Created Time desc | a new Credit record matching the voucher, created around the same time as the invoice |
| Did the member get the 7-day heads-up email? | Contact → Emails related list, and the Last_Nurture_Sent field | an email with subject "Your next payment..." about a week before Package_Expiry_Date, and Last_Nurture_Sent updated to that date |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| The whole credit top-up on renewal (both orgs) | Zoho Flow → disable flow "ZBilling-ZCRM_INV_CREATION" (folder Zoho Billing - Zoho CRM) | Stops GolfManager voucher top-ups and new CRM Credits records for every renewal invoice; does not stop Billing from still charging cards or emailing invoices |
| The Contact balance roll-up | Setup → Automation → Workflow Rules → Credits → "GM Sync - Credits to Contact EngineA" | New Credits records still get created, but Contact-level balance fields stop refreshing |
| The 7-day reminder email | Setup → Automation → Workflow Rules → Contacts → "RENEW R-3 — 7-Day Renewal Reminder" | Members stop getting the pre-renewal heads-up email |
Good to know
GolfManager's membership record doesn't change on renewal
The subscriptionCustomer (membership) record in GolfManager is created once at signup and stays active indefinitely; a monthly renewal only tops up the linked voucher/credit, it never recreates or edits the membership record itself.
Both orgs run on the same daily rhythm
DIFC's renewal batch runs first each morning (~06:00–06:05 Dubai), Studio City's runs a bit later (~06:17–06:18) — both driven by whatever time each org's subscriptions were originally started.
The plan-to-credit mapping is a fixed lookup table
UpdateMembershipCredits_CRM_SubscriptionInv maps roughly 15 known plan codes to specific credit names/types/balances by hardcoded number. A brand-new plan added in Zoho Billing needs a matching branch added here so its renewal credits are recognized.
Credit expiry dates drift with invoice time, not billing date
Expiry is calculated as "today + 30 days" at the moment the function runs, so if a renewal invoice is created a few minutes later one month than another, the credit's expiry date shifts by the same amount.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (5)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Zoho Billing autobilln/a (native Billing feature, not a Deluge function) | other | Unknown | Subscription's recurring billing date autobill_status must be "live" on the subscription | Charges the saved card and syncs a matching invoice into Zoho Books (transaction_type:"renewal", sales_channel:"direct_sales", is_emailed:true). No live tool in this session reads Zoho Billing directly; effects observed only via the Books invoice it creates. | Zoho Billing › Subscriptions n/a |
ZBilling-ZCRM_INV_CREATION469029000000062505 | flow | Active last run 2026-09-23T06:21 | Webhook on new Books/Billing invoice Fires for every Billing-originated invoice; this flow's own node graph could not be opened in the Flow UI at capture time (one of the archive's unopenable flows) — wiring inferred from the function's recorded flow mapping, not the flow graph itself | Calls function UpdateMembershipCredits_CRM_SubscriptionInv(invoice_id, org_id). | Zoho Flow › folder "Zoho Billing - Zoho CRM", link_name zohobilling_zohocrm $HOME/arch/flow_deluge_source/UpdateMembershipCredits_CRM_SubscriptionInv.deluge |
UpdateMembershipCredits_CRM_SubscriptionInvflow_functions.json id 469029000000062535 (userWorkflowId 469029000000062500) | function | Active last run 2026-09-23T06:21 | invoked with (invoice_id, org_id) Skips the invoice if the Books contact's email doesn't match a CRM Contact, or if the Billing plan's custom field (cf_gm_membership_type_id at SC / cf_gm_membership_type_id_1 at DIFC) doesn't match one of ~15 hard-coded numeric plan codes | Re-fetches the Books invoice, matches CRM Contact by email (no create-if-missing fallback; takes no further action if no match), re-fetches the Billing invoice+plan to read the plan's membership-type custom field, maps that numeric code through a hard-coded if/else-if ladder to a credit name/GolfManager voucher type/balance/price, recharges a GolfManager voucher, then creates a matching CRM Credits record. Addon plans (codes 17/40) are handled separately by scanning line items for a "Membership - ADD on" item. | called by ZBilling-ZCRM_INV_CREATION $HOME/arch/flow_deluge_source/UpdateMembershipCredits_CRM_SubscriptionInv.deluge |
GM Sync - Credits to Contact EngineA6296422000045075173 | workflow rule | Active last run 2026-10-12T06:06 | Credits module, create or edit Fires on every Credits create/edit, including the renewal top-up | Calls function syncContactCredits(contactId) — re-sums all of the Player's live Credits by category onto the Contact's balance/expiry fields (same function used by the store-purchase and pos-sale flows). | CRM › Setup › Automation › Workflow Rules › module Credits $HOME/arch/crm_deluge_source/synccontactcredits.deluge |
RENEW R-3 — 7-Day Renewal Reminder6296422000045650199 | workflow rule | Active last run 2026-10-12T00:01 | Contacts, date-based: Package_Expiry_Date - 7 days, once Lifecycle_Status in an active-member set (Member/6 Month Member/Beginner Member/Junior Member); Subscription_Interval = Monthly; not mid-onboarding; Last_Nurture_Sent empty or more than 4 days ago (comparator was inverted to less_than from 2026-07-04, which blocked almost every member; fixed to greater_than 2026-09-30); Renewal_Cancelled = false (added 2026-10-14 after a member who had cancelled at term end got the "continues as normal" email; flag written nightly by sfaLifecycleStatusSweep v4 from the winning Billing membership status non_renewing); not in the "Needs Card Update" dunning stage | Sends CRM email template "E-3 Email One Week Renewing" (notification id 6296422000045723131) and stamps Last_Nurture_Sent via a linked function. | CRM › Setup › Automation › Workflow Rules › module Contacts CRM email notification 6296422000045723131; no separate .deluge file found — likely a pure field-update/email-template action, not a custom function |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Books invoice | transaction_type / sales_channel / autobill_status | renewal / direct_sales / live — marks this as an autobill renewal invoice | Zoho Billing at renewal |
| Books invoice | cf_golfmanager_membership_id | Points at the GolfManager subscriptionCustomer (membership) record this renewal belongs to | Set at signup, carried on every renewal invoice |
| Billing plan | cf_gm_membership_type_id (SC) / cf_gm_membership_type_id_1 (DIFC) | Numeric plan code the credit-mapping ladder switches on | Set manually on the Billing plan |
| Credits | Reference_ID | Intended to link the CRM Credit back to its GolfManager voucher id | UpdateMembershipCredits_CRM_SubscriptionInv — currently always blank (reads recharge_resp.get("voucher").get("id"), but the GolfManager recharge endpoint's actual response key is "sale", not "voucher", per the working sibling function UpdateCreditinGolfManager) |
| Contacts | Last_Nurture_Sent | Cooldown stamp shared across multiple nurture rules (RENEW R-3, CREDITUP, etc.) to avoid over-messaging | RENEW R-3's linked function and others |
| Contacts | Member_Lesson_Credit_Balance, Credit_Expiry_Date, etc. | Roll-up totals refreshed by every Credits create/edit including renewals | syncContactCredits |
Full email text
RENEW R-3 — 7-Day Renewal Reminder (E-3 Email One Week Renewing)Your next payment: Players.Membership Expiry Date
Renewal invoice / autobill charge noticeInvoice from SwingFIT Academies — invoice number
Payment receiptPayment confirmed
IDs and references
| What | Value |
|---|---|
| Books org, Studio City | 866469739 |
| Books org, DIFC | 872210045 |
| GolfManager voucher type, standard monthly member lesson credit | 254 (plan codes 9/13/18/19/20/21/35) |
| GolfManager voucher type, Senior PGA | 270 (plan codes 22-25) |
| GolfManager voucher type, Beginner Membership Credit | 272 (plan codes 100/39) |
| GolfManager voucher type, Junior / Young Junior Membership Credit | 273 / 274 (plan codes 101/102) |
| Zoho Creator commission app | creator.zoho.com/api/v2/swingfitacademies/golf-manager — report All_Salespeople |
All flows › Annual renewal and card expiry
Annual and 6-month renewals, and card-expiry reminders
Members with annual/6-month plans get renewal nurture emails at 45 and 30 days out, and everyone gets card-expiry reminders at 30 and 15 days, with a self-refreshing card-update link.
- Starts when
- A Contact's Package_Expiry_Date or Card_Expiry_Date field crosses a fixed number of days out. Zoho CRM's date-based workflow rules check this once daily, just after midnight Dubai time, and fire for any Contact that matches that day.
- Covers
- Covers the pre-renewal nurture emails sent to Annual and 6-Month members (RENEW R-1 at 45 days, R-2 at 30 days) and the card-expiry reminder emails sent to all active members (PD-1 at 30 days, PD-2 at 15 days), plus how Package_Expiry_Date and Card_Expiry_Date get into CRM and how the "Update your card" link in those emails stays live. The monthly 7-day renewal reminder (RENEW R-3) and the credit top-up mechanics on a successful renewal charge are covered in membership-renewal — this trace links to that one rather than repeating it. Failed-payment dunning (PD-3, T14, Dunning_Stage) is a separate flow.
- Systems
- Zoho CRM, Zoho Billing
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- daily ~02:00 Dubainightly Billing syncZoho Billing
Card and renewal dates land in CRM from Zoho Billing
Verified liveA nightly schedule (
Billing Memberships Daily Sync) pulls every Billing subscription in both orgs and, for live subscriptions, stamps the matching Contact'sPackage_Expiry_Date,Subscription_Interval,Billing_Org_IDandCard_Expiry_Date.Package_Expiry_Dateis the next charge date for monthly members, and the end of the current contract term for annual and 6-month members (moved forward each term). This is the only thing that writes that date, and every renewal reminder counts down to it.See itContact record -> Package_Expiry_Date / Card_Expiry_Date / Subscription_Interval fields; Memberships records show Modified ~02:00 each night. - daily ~03:00 Dubaicard-link refreshZoho CRM
The card-update link for soon-to-expire cards is refreshed
UnverifiedA daily schedule looks at every active member whose
Card_Expiry_Datefalls within the next 35 days, requests a fresh card-update link from Zoho Billing for that member's subscription, and writes it into the Contact'sUpdate_Card_Linkfield. This is what the "Update your card" button in the PD-1/PD-2 emails is designed to point to.See itContact record → Update_Card_Link field - T-45 days (Package_Expiry_Date)45-day renewal nurtureZoho CRM
Annual members get a 45-day renewal heads-up
Verified liveRENEW R-1 - 45-Day Annual Renewalfires for Contacts withSubscription_Interval = Annual, skipping anyone still in their first 30 days, nurtured in the last 4 days, with a card expiring within 10 days, or already flagged as needing a card update. It stampsLast_Nurture_Sentand sends the RENEW R-1 email.See itContact → Emails related list; Last_Nurture_Sent field - T-30 days (Package_Expiry_Date)30-day renewal nurtureZoho CRM
Annual and 6-month members get a 30-day renewal heads-up
UnverifiedRENEW R-2 - 30-Day Annual and 6Month Renewalruns the same criteria as R-1 but forSubscription_Intervalin Annual or 6-Month, and sends the RENEW R-2 email. It shares the same suppression logic (onboarding, recent nurture, near card expiry, active dunning).See itContact → Emails related list - T-30 days (Card_Expiry_Date)30-day card-expiry reminderZoho CRM
Members get a 30-day card-expiry reminder
Verified livePD-1 — 30-Day Card Expiry Reminderfires for active members (Member, 6 Month Member, Beginner Member or Junior Member) and sends an email with an "Update your card" button.See itContact → Emails related list - T-15 days (Card_Expiry_Date)15-day card-expiry reminderZoho CRM
Members get a 15-day card-expiry reminder
Verified livePD-2 — 15-Day Card Expiry Reminderruns the same criteria as PD-1 and sends a firmer follow-up on the same card.See itContact → Emails related list - on demandstaff-triggered card linkZoho CRM
Staff can generate a card-update link by hand
From codeThe "Update Card Link" button on a Membership record calls the same Billing link API on the spot and returns a one-hour link staff can copy straight into a message to the member — useful when someone calls in about a card rather than waiting for the nightly refresh.
See itMemberships → open a record → "Update Card Link" button
Emails and messages
CustomerRENEW R-1 — 45-Day Annual RenewalVerified live12 months. Here's what you've built.
Full text (crm_email_templates/RENEW/E-1-renewal-45day.html)
CustomerRENEW R-2 — 30-Day Annual and 6-Month RenewalUnverified30 days out — here's where your game stands
Full text (crm_email_templates/RENEW/E-2-renewal-30day.html)
CustomerPD-1 — 30-Day Card Expiry ReminderVerified liveYour card on file expires in 30 days
Full text (crm_email_templates/PREDUN/PD-1-card-expiry-30day.html)
CustomerPD-2 — 15-Day Card Expiry ReminderVerified live15 days left on the card on file for your membership
Full text (crm_email_templates/PREDUN/PD-2-card-expiry-15day.html)
CustomerZoho Billing's own card-expiry notifications (Card Expiring Soon / Card Expired)UnverifiedYour card expires soon — update it to keep your membership / Your card has expired — update it now
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Is a member due a 45- or 30-day renewal reminder? | Contact → Package_Expiry_Date field, and the Subscription_Interval field | Package_Expiry_Date is 45 or 30 days out and Subscription_Interval matches (Annual for R-1; Annual or 6-Month for R-2) |
| Did the renewal reminder actually send? | Contact → Emails related list | an email from info@swingfitacademies.com with the R-1 or R-2 subject line, dated the trigger day |
| Is a member due a card-expiry reminder? | Contact → Card_Expiry_Date field | Card_Expiry_Date is 30 or 15 days out and Lifecycle_Status is Member / 6 Month Member / Beginner Member / Junior Member |
| Will the "Update your card" button in a PD-1/PD-2 email actually work for this member? | Contact → Update_Card_Link field | a zoho subscriptions hosted-page URL, refreshed within the last day or so |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| 45-day annual renewal reminder | Setup → Automation → Workflow Rules → Contacts → "RENEW R-1 - 45-Day Annual Renewal" | Annual members stop getting the 45-day heads-up email |
| 30-day annual/6-month renewal reminder | Setup → Automation → Workflow Rules → Contacts → "RENEW R-2 - 30-Day Annual and 6Month Renewal" | Annual and 6-Month members stop getting the 30-day heads-up email |
| 30-day card-expiry reminder | Setup → Automation → Workflow Rules → Contacts → "PD-1 — 30-Day Card Expiry Reminder" | members stop getting the 30-day card-expiry email |
| 15-day card-expiry reminder | Setup → Automation → Workflow Rules → Contacts → "PD-2 — 15-Day Card Expiry Reminder" | members stop getting the 15-day card-expiry email |
| card-update link refresh | Setup → Automation → Schedules → "Predun_Refresh" | Update_Card_Link stops refreshing, so the "Update your card" button in PD-1/PD-2 emails goes stale after about an hour |
Good to know
R-1 and R-2 share the same guardrails
Both rules skip anyone still in their first 30 days (In_Onboarding), anyone nurtured in the last 4 days (Last_Nurture_Sent), anyone whose card is already expiring within 10 days, and anyone flagged Dunning_Stage = Needs_Card_Update — so a member mid-dunning isn't also hit with a routine renewal nudge.
One throttle function serves many rules
The Last_Nurture_Sent function that R-1 and R-2 call to stamp their send date is shared with a dozen other nurture rules (R-3, winback, inactive retention) — it's the org-wide way rules avoid double-messaging the same Contact.
The card-update link is short-lived by design
A Billing hosted-page link for updating a card is only valid for about an hour, which is why Update_Card_Link is refreshed by a daily schedule rather than generated once and left in the field.
Staff have a manual fallback
The "Update Card Link" button on a Membership record generates a fresh one-hour link on the spot, for when a member calls in rather than clicking the email.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (11)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
RENEW R-1 - 45-Day Annual Renewal6296422000045652083 | workflow rule | Active last run 2026-09-01T00:02 | date_or_datetime, Package_Expiry_Date -45 days, recur once Subscription_Interval = Annual AND (Card_Expiry_Date empty OR >10 days out) AND (In_Onboarding empty OR <30 days ago) AND (Last_Nurture_Sent empty OR more than 4 days ago; comparator fixed less_than→greater_than 2026-09-30) AND (Dunning_Stage empty OR != Needs_Card_Update) | Calls function Last_Nurture_Sent(contactId) to stamp today's date, then sends the RENEW R-1 email notification. | Setup → Automation → Workflow Rules → Contacts n/a (native workflow rule + email notification, no custom function beyond Last_Nurture_Sent) |
RENEW R-2 - 30-Day Annual and 6Month Renewal6296422000045669078 | workflow rule | Active last run 2026-07-03T00:02 | date_or_datetime, Package_Expiry_Date -30 days, recur once Subscription_Interval in (Annual, 6-Month) AND (Card_Expiry_Date empty OR >10 days out) AND (In_Onboarding empty OR <30 days ago) AND (Last_Nurture_Sent empty OR more than 4 days ago; comparator fixed less_than→greater_than 2026-09-30) AND (Dunning_Stage empty OR != Needs_Card_Update) | Calls function Last_Nurture_Sent(contactId), then sends the RENEW R-2 email notification. | Setup → Automation → Workflow Rules → Contacts n/a (native workflow rule + email notification, no custom function beyond Last_Nurture_Sent) |
RENEW R-3 — 7-Day Renewal Reminder6296422000045650199 | workflow rule | Active last run 2026-10-12T00:01 | date_or_datetime, Package_Expiry_Date -7 days, recur once see membership-renewal trace | Covered fully in the membership-renewal flow; linked here because it fires from the same Package_Expiry_Date field. | Setup → Automation → Workflow Rules → Contacts (see membership-renewal for full detail) n/a |
PD-1 — 30-Day Card Expiry Reminder6296422000045943009 | workflow rule | Active last run 2026-10-02T00:02 | date_or_datetime, Card_Expiry_Date -30 days, recur once Lifecycle_Status in (Member, 6 Month Member, Beginner Member, Junior Member) | Sends the email notification PREDUN Card Expiry - 30 Day. | Setup → Automation → Workflow Rules → Contacts n/a (email notification only, no function action) |
PD-2 — 15-Day Card Expiry Reminder6296422000045945009 | workflow rule | Active last run 2026-09-16T00:02 | date_or_datetime, Card_Expiry_Date -15 days, recur once Lifecycle_Status in (Member, 6 Month Member, Beginner Member, Junior Member) | Sends the email notification PREDUN Card Expiry - 15 Day. | Setup → Automation → Workflow Rules → Contacts n/a (email notification only, no function action) |
PD-3 — 7-Day Card Expiry Reminder6296422000045868010 | workflow rule | Inactive | date_or_datetime, Card_Expiry_Date -7 days, recur once same Lifecycle_Status shape expected as PD-1/PD-2 (description carries a "DO NOT ACTIVATE without testing" note) | Would send a PREDUN Card Expiry - 7 Day email notification; not currently wired to run. | Setup → Automation → Workflow Rules → Contacts crm_email_templates/PREDUN/PD-3-card-expiry-7day.html (template exists, not confirmed live) |
Last_Nurture_Sent1446733000000615006 (function) / action id 6296422000045556032 on R-1, action id used on R-2 | function | Active | called as an instant action from RENEW R-1, R-2, R-3 and several other nurture rules runs unconditionally when called; the calling rule's own criteria is the gate | Stamps Contacts.Last_Nurture_Sent with today's date for the given contactId. Shared across ~10 nurture-family rules as the org-wide send-throttle mechanism. | Setup → Automation → Functions $HOME/arch/crm_deluge_source/last_nurture_sent.deluge |
Billing Memberships Daily Sync (function swingfit_sync_membership)6296422000045556008 | schedule | Active last run 2026-10-01T02:12 | daily, 02:00 Asia/Dubai loops both Books/Billing orgs (866469739, 872210045); subscription status in live/paused/dunning/non_renewing/future | Creates/updates Memberships and Practice_Passes records, stamps Billing_Org_ID, Sync_Status, and on the Contact: Subscription_Interval, Package_Expiry_Date, and Card_Expiry_Date (from the subscription card's expiry_month/expiry_year, only when status is "live"). Also marks Sync_Status=Stale on drift and can send an alert email to max@swingfitacademies.com. | Setup → Automation → Schedules automation/deluge/swingfit_sync_memberships_DRAFT_2026-09-30-expiry-owner.deluge |
sfaBillingExpirySync6296422000045723129 | schedule | Off last run 2026-09-02T02:04 | daily, 02:00 Asia/Dubai loops both Billing orgs, subscriptions filtered SubscriptionStatus.ACTIVE | RETIRED 2026-09-30 (schedule switched off). Used to write Package_Expiry_Date from current_term_ends_at but only read the first 200 subscriptions, so the oldest Studio City members never synced. | Setup → Automation → Schedules $HOME/arch/crm_deluge_source/sfabillingexpirysync.deluge |
Predun_Refresh (function likely PredunLink / swingfit_predun_link_refresh)6296422000027201131 | schedule | Active last run 2026-09-02T03:03 | daily, 03:00 Asia/Dubai Contacts with Lifecycle_Status in Member/Beginner Member/6 Month Member/Junior Member whose Card_Expiry_Date is 0-35 days out and who have an active Memberships record | Requests a Zoho Billing hosted-page "update card" link for the member's subscription and writes the URL into Contacts.Update_Card_Link, which PD-1/PD-2 emails link to. | Setup → Automation → Schedules $HOME/arch/crm_deluge_source/predun_link_refresh.deluge and swingfit_predun_link_refresh.deluge (near-identical); $HOME/arch/crm_deluge_source/updatecardlink.deluge is an empty stub (void schedule.UpdateCardLink(){}) |
sfaUpdateCardLink ("Update Card Link" button)n/a (button function) | button | Active | manual click by staff, passes the Membership record's id requires the Membership to have Subscription_ID and Billing_Org_ID populated | Calls Zoho Billing's hostedpages/updatecard API directly for that membership's subscription and returns a one-hour link as a popup message for staff to copy and send. | Memberships module → record page → "Update Card Link" button domains/member-success/sfaUpdateCardLink.deluge ($HOME/arch/crm_deluge_source/sfaupdatecardlink.deluge) |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Contacts | Package_Expiry_Date | Date the member's current billing term/renewal is due; drives RENEW R-1/R-2/R-3 | Billing Memberships Daily Sync (swingfit_sync_membership) only, since 2026-09-30: Monthly = next charge date; Annual/6-Month = current contract-term end, rolled forward each term |
| Contacts | Card_Expiry_Date | Expiry month/year of the card on file in Zoho Billing, stored as YYYY-MM-01; drives PD-1/PD-2/PD-3 | Billing Memberships Daily Sync (swingfit_sync_membership) |
| Contacts | Subscription_Interval | Annual / 6-Month / Monthly — determines which renewal rules a Contact is eligible for | Billing Memberships Daily Sync (swingfit_sync_membership) |
| Contacts | Update_Card_Link | Zoho Billing hosted-page URL for updating the card on file; used as the button href in PD-1/PD-2 emails | Predun_Refresh schedule (daily, for cards expiring within 35 days) |
| Contacts | Dunning_Stage | Marks a Contact in active payment dunning (e.g. Needs_Card_Update); used to suppress routine renewal nudges | dunning flow (separate from this trace) |
| Contacts | Last_Nurture_Sent | Date a nurture-family email last went to this Contact; throttles repeat sends across R-1/R-2/R-3 and others | Last_Nurture_Sent function, called by each nurture rule |
| Contacts | In_Onboarding | Date onboarding started; Contacts inside their first 30 days are excluded from R-1/R-2 | onboarding flow (separate from this trace) |
| Contacts | Lifecycle_Status | Member / 6 Month Member / Beginner Member / Junior Member / Churned Member / Expired / Client — gates PD-1/PD-2 eligibility | sfaLifecycleStatusSweep (separate schedule, sole owner per 2026-08-17 decision) |
Full email text
PD-3 (PD-3-card-expiry-7day)not confirmed (rule inactive)
Zoho Billing native T15 Card Expiring SoonYour card expires soon — update it to keep your membership
Zoho Billing native T16 Card ExpiredYour card has expired — update it now
IDs and references
| What | Value |
|---|---|
| Books/Billing org — Studio City | 866469739 |
| Books/Billing org — DIFC | 872210045 |
| RENEW R-1 rule id | 6296422000045652083 |
| RENEW R-2 rule id | 6296422000045669078 |
| PD-1 rule id | 6296422000045943009 |
| PD-2 rule id | 6296422000045945009 |
| PD-3 rule id (inactive) | 6296422000045868010 |
| Billing Memberships Daily Sync schedule id | 6296422000045556008 |
| sfaBillingExpirySync schedule id | 6296422000045723129 |
| Predun_Refresh schedule id | 6296422000027201131 |
All flows › Payment failure
When a membership payment fails
When a monthly card charge fails, Zoho Billing retries it and emails the member, CRM mirrors the dunning status, and staff get alerted to follow up.
- Starts when
- A member's card is auto-charged on their subscription's Next_Billing_Date in Zoho Billing and the charge fails (expired card, bank decline, insufficient funds).
- Covers
- Covers a recurring monthly/annual SwingFIT membership subscription (Zoho Billing) failing its scheduled auto-charge: the Billing-side status change, the nightly sync into CRM, Billing's own dunning emails to the member, the daily staff Cliq alert, GolfManager access, and how the case resolves. Does NOT cover one-off lesson/booking payment failures at time of booking (separate
Zoho Bookings Payment Failure/ZBookings to CRMPlayer - Payment Failedflows) or Zoho Books invoice-level reminders (checked live — unused on the invoices traced here, reminders_sent:0). - Systems
- Zoho Billing, Zoho CRM, Zoho Books, GolfManager, Zoho Cliq, Gmail (internal copies of automated emails)
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0charge attempt failsZoho Billing
Zoho Billing tries to auto-charge the card and it fails
From codeZoho Billing runs its own charge-retry cadence and dunning-stage logic for the subscription (org-wide Billing settings — not something CRM or a Deluge function controls). On the first failure the subscription's native
statusmoves todunning. Billing's dunning settings also email the member about the failed payment.See itZoho Billing > Subscriptions > the subscription record > Payment History / Status. - T+~2-24h (nightly 02:00-03:00 Dubai)nightly Billing→CRM syncZoho CRM
CRM's Membership record mirrors the Billing status verbatim
Verified liveThe
swingfit_sync_membershipschedule (display name 'Billing Memberships Daily Sync') pulls every subscription from both Billing orgs (Studio City 866469739, DIFC 872210045) and copies the raw Billingstatusstring straight into the matching CRMMemberships.Statusfield —dunningis one of five statuses (live,paused,dunning,non_renewing,future) it still treats as 'active enough' not to mark the CRM record stale. It also stampsOutstandingfrom Billing's balance.- Real exampleVerified live2026-09-23 02:09
Membership SFA-00037, invoice SFA/2026/02762: shows Status=
dunning, Outstanding=997, Modified_Time 2026-09-23T02:09:36+04:00 — matching this sync's nightly window (overdue 3 days at the time).
See itCRM > Memberships module > the player's Membership record > Status + Outstanding fields. - daily 09:00 Dubaistaff alertCliq
sfaDunningTeamAlert DMs the assigned salesperson (or Akash) with an update-card link
UnverifiedsfaDunningTeamAlertpulls every overdue invoice (balance ≥ AED 100, due since watermark 2026-07-16) and everyPAST_DUE/UNPAIDsubscription from both Billing orgs, generates a 1-hour hosted-page "update card" link per case, and is designed to Cliq-DM the case list to the subscription's assigned salesperson for the first 10 days, then escalate to Akash (also the default for unmapped/inactive salespeople). Cases 30+ days overdue get a 🔴 flag. Whether this is confirmed live and sending to staff today is unverified.See itCRM > Automation > Schedules >sfadunningteamalert. Ask the assigned salesperson whether they got a Cliq DM frommembershipbottoday. - throughoutmember accessGolfManager
Nothing changes in GolfManager while a membership is in dunning
Verified liveThere is no automatic link between Billing/CRM dunning status and GolfManager booking access. The GolfManager customer record has a
disabled(Blocked) flag and apendingbalance field, but nothing in this flow setsdisabled=truewhen a membership goes into dunning.- Real exampleUnverified
GolfManager customer 9325: disabled=false, pending=AED 5,783 — booking access continues normally while the linked CRM Membership is in Status=dunning.
See itGolfManager > Customers > the player record > Blocked / Pending fields. - resolutionhow it endsZoho Billing
Paid, cancelled, or paused
From codePaid: the member updates their card (via the hosted-page link or manually) and Billing's next retry succeeds — subscription status flips back to
livein Billing, and the next nightly sync mirrors that into CRM Memberships.Status, which naturally stops the dunning emails and staff alerts (they only fire while the balance/status still qualifies). Cancelled: if Billing's own retry limit is exhausted before payment is recovered, Billing moves the subscription tocancelled/expired; the nightly sync mirrors that status into CRM, and the cancellation side (ZBilling_SubscriptionCancel_ZohoFormsflow,sfaCancellationSweep, T19 template) picks it up as it would any other cancellation. Paused: a member-requested pause is a separate path (PauseCancel_Request records handled bysfaCancellationSweep/Pause journey) — not a direct outcome of a failed payment.See itCRM Memberships.Status returning tolive, or moving tocancelled/expired.
Emails and messages
CustomerPayment failed — action neededUnverifiedAbout your membership payment — action needed
CustomerPayment failed — still outstandingUnverifiedAbout your membership payment — still outstanding
TeamDaily dunning case listUnverifiedn/a (Cliq DM, not email)
Full text (function code (domains/member-success/sfaDunningTeamAlert.deluge))
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Is this member's payment actually failing right now? | CRM > Memberships > their record > Status + Outstanding | Status = dunning and Outstanding matches the Books invoice balance. |
| Did the customer actually receive the payment-failed email? | CRM > Contacts > the contact > Emails related list (sent_time, to address). | An entry with the customer's own email as recipient and a recent sent_time. |
| Is this case sitting with the right salesperson? | Ask the salesperson to check Cliq for a DM from membershipbot, or check CRM Memberships > salesperson field. | They can name the case from their Cliq DM. |
| Will this member still be able to book while unpaid? | GolfManager > Customers > their record > Blocked (disabled) field. | disabled stays false unless someone manually blocks them — there is no automatic cutoff. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Customer dunning emails | Zoho CRM > Automation > Schedules > swingfit_dun_scan | No more "action needed"/"still outstanding" emails go out at all. |
| Staff Cliq alerts | Zoho CRM > Automation > Schedules > sfadunningteamalert | Salespeople and Akash stop getting the daily case-list DM; unmapped-salesperson/error alerts to Max also stop. |
| Billing → CRM status mirror | Zoho CRM > Automation > Schedules > swingfit_sync_membership ("Billing Memberships Daily Sync") | Memberships.Status stops updating from Billing entirely — breaks dunning detection for both functions above and for the Lifecycle_Status sweep that depends on it. |
Good to know
Status is a straight copy, not a CRM decision
CRM never decides a membership is "in dunning" — it just mirrors whatever raw status string Zoho Billing reports (live, dunning, non_renewing, paused, cancelled, expired, future) once a night.
dunning still counts as "active-ish"
The nightly sync's own active_statuses list includes dunning and non_renewing alongside live — a membership can sit in dunning for days without being treated as churned by that sync.
Update-card links expire fast
The hosted-page "update card" link sfaDunningTeamAlert generates for staff is only valid for 1 hour; a fresh one comes from the "Update Card Link" button on the Membership record.
Salesperson ownership window
A case sits with the subscription's assigned salesperson for the first 10 days after the balance first appeared; after that (or if unmapped/inactive salesperson) it escalates to Akash.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (3)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Zoho Billing native dunning/retry cadencen/a (Billing org setting, not a CRM/Flow object) | other | Active | Scheduled auto-charge on a subscription's Next_Billing_Date fails n/a - platform-level retry schedule and dunning-stage rules configured in Billing's own settings, not visible to CRM tools | Retries the charge per Billing's own cadence and flips the subscription's native status to dunning on first failure, then to cancelled/expired if the retry limit is exhausted with no payment recovered. Billing's own dunning settings also send the member the payment-failed emails; there is no CRM-side customer dunning email (swingfit_dun_scan was retired 2026-09-30 - it filtered on a status that never exists and never sent anything). | Zoho Billing > Settings > Automation > Dunning n/a (Zoho Billing platform config, no Deluge source) |
Billing Memberships Daily Sync6296422000045556008 | schedule | Active last run 2026-09-02T03:03 | daily 02:00 Dubai none - pulls every subscription from both Billing orgs each run | Calls function billing_memberships_daily_sync (internal_name swingfit_sync_membership) to pull every subscription from Books/Billing orgs Studio City (866469739) and DIFC (872210045), copy the raw Billing status string (live, paused, dunning, non_renewing, future, cancelled, expired) straight into CRM Memberships.Status, and stamp Memberships.Outstanding from Billing's balance. Its own active_statuses list still counts dunning and non_renewing as active enough not to mark the record stale. | Zoho CRM > Setup > Automation > Schedules crm_deluge_source/billing_memberships_daily_sync.deluge |
sfadunningteamalert6296422000047169009 | schedule | Active last run 2026-09-02T09:04 | daily 09:00 Dubai overdue Books invoices with balance >= AED 100, due since watermark 2026-07-16, across both Billing orgs; plus subscriptions in PAST_DUE/UNPAID status | Generates a 1-hour hosted-page 'update card' link per case and Cliq-DMs the case list (via bot membershipbot) to the subscription's assigned salesperson for the first 10 days, then escalates to Akash (also the fallback for unmapped/inactive salespeople); flags cases 30+ days overdue with a red-circle marker. | Zoho CRM > Setup > Automation > Schedules domains/member-success/sfaDunningTeamAlert.deluge (per function-registry.md); archive copy at crm_deluge_source/sfadunningteamalert.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Memberships | Status | Mirror of the Billing subscription's raw status string (live/dunning/paused/non_renewing/future/cancelled/expired) | Billing Memberships Daily Sync (billing_memberships_daily_sync) |
| Memberships | Outstanding | Balance owed, copied from the Billing subscription/invoice | Billing Memberships Daily Sync (billing_memberships_daily_sync) |
| Contacts | Dunning_Stage | Set to 'Needs_Card_Update' when the first dunning email is queued, 'Recovered' when the balance clears | swingfit_dun_scan (retired 2026-09-30; no longer written) |
| Contacts | Last_Dunning_Touch | Date of the most recent dunning send; used as a 2-day de-dup guard before the next send | swingfit_dun_scan (retired 2026-09-30; no longer written) |
Full email text
T14-Payment-Failed (Billing template library — appears unused for this live flow)Action needed — your payment didn't go through
DN-02 payment-failed (dunning design library — appears unused for this live flow)Your payment didn't go through — update your card
IDs and references
| What | Value |
|---|---|
| Zoho Books org — Studio City | 866469739 |
| Zoho Books org — DIFC | 872210045 |
| CRM email template — 'action needed' dunning email | 6296422000046175022 |
| CRM schedule — Billing Memberships Daily Sync | 6296422000045556008 |
| CRM schedule — swingfit_dun_scan | 6296422000046175033 |
| CRM schedule — sfadunningteamalert | 6296422000047169009 |
All flows › Retention and at-risk
When a member goes quiet or is at risk of leaving
Daily scans flag quiet or churned members for staff and members alike, running an absence nudge, a 30/60/90-day win-back drip after cancellation, and a welcome-back note if they return.
- Starts when
- Two triggers run this flow: a daily scheduled scan across every active member (for the at-risk digest and the absence ladder), and a Cancel request logged against a Churned Member (for the win-back drip).
- Covers
- Covers how SwingFIT spots a member who has gone quiet, the absence follow-up that runs while they're still a member, the churn win-back drip once they've cancelled, and the welcome-back note if they return. Does not cover the single-lesson rebooking nudge (see lesson-booking) or lead/prospect re-engagement, which targets people who never converted (a different audience, not covered here).
- Systems
- Zoho CRM, Email
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- daily 08:00 Asia/DubaiDaily 8amZoho CRM
Staff get a daily at-risk digest
From codeatrisk_scanchecks every live Member (all pages) and every active PAYG customer each morning. Paused members are skipped and future-dated bookings are ignored. It flags anyone 10-20 days since their last past booking with nothing booked ahead, or whose booking count dropped 40%+ over the last 30 days versus the 30 before (only when the prior 30 days had 4+ bookings). Anyone 21+ days away with nothing booked ahead goes in a separate Lapsed section. Bookings count unless Cancelled or Not Completed, so this is booked, not attended. Flagged contacts get a 7-day cooldown (Last_ATRISK_Alert) so the same person isn't re-flagged daily.See itContacts › flagged record ›Last_ATRISK_Alertfield (stamped the day it's flagged). The summary email lands in the leadership inboxes each morning, split into Drifting and Lapsed 21+ days, grouped by Coaching / Practice-only / Plan Unclear / PAYG. - T+5 to T+14 days of inactivityAbsence ladderZoho CRM
A quiet member moves through a 3-stage absence ladder
From codesfaAbsenceLadderruns daily against live Members. It skips paused members, members with an upcoming booking and members with no live membership, and measures absence from the last past booking. Members who return inside 5 days reset to stage 0. Only the Day-10 email is active; the Day-5 and Day-14 touchpoints are planned.- Day 5 — WhatsApp nudgeUnverifiedT+5d
Reserved for a WhatsApp check-in once the consolidated WhatsApp send is live; today nothing is sent and no stage is stamped.
- Day 10 — email nudgeUnverifiedT+10d
Sends a "your plan is still here, book your next session" email via template, gated by onboarding/dunning/card-expiry/4-day frequency-cap checks shared with the rest of the retention flow.
- Day 14 — Member Success hand-offUnverifiedT+14d
Designed to create a follow-up task for the Member Success team so a person reaches out. Not wired up; no stage is stamped.
See itContacts ›Absence_Stagefield (0 = not absent / reset, 1 = day-5 stage, 2 = day-10 stage, 3 = day-14 stage). - T+0 on Cancel requestCancellation loggedZoho CRM
A cancelled member is queued for churn win-back
Verified liveWhen a Contact's
PauseCancel_Request(Request_Type = Cancel) belongs to someone whoseLifecycle_Statusis Churned Member,sfaBoomSweeppicks it up daily and starts a reason-matched, 3-step drip timed off the cancellation date. It records a reason-specific line of copy on the request record and stampsWinback_Startedon the Contact on the first send.- +30 days — check-inVerified liveT+30d
"How's the game going?" — a no-agenda check-in, no pitch.
- +60 days — reason-matched follow-upVerified liveT+60d
Answers the specific reason they gave for cancelling (cost, scheduling, coaching fit, facilities, relocation, etc.) with a direct, tailored line.
- +90 days — final inviteVerified liveT+90d
Closing note: their TrackMan history and plan are still on file, one evaluation puts them back in. After this the drip is exhausted and the contact is left to the list-hygiene sweep on its own timeline.
See itPauseCancel_Request record ›Boom_Stage(0-3) andBoom_Stage_Changed; Contacts ›Winback_Started. - T+0 on next booking, 60+ day gapMember returnsZoho CRM
A returning member gets a one-time welcome-back note
UnverifiedsfaReonboardWelcomeruns daily against today's bookings. If a booking's customer has a prior booking 60+ days earlier (and hasn't had a reonboard email in the last 90 days), it sends a one-time "good to see you back" email and resets theirWinback_StartedandAbsence_Stageso they re-enter the normal flow cleanly.See itContacts ›Reonboard_Last_Sentfield.
Emails and messages
TeamAt-risk check (staff digest)From codeAt-risk check — date (drifting drifting, lapsed lapsed)
Full text (function code (atrisk_scan.deluge))
CustomerAbsence Day-10 nudgeUnverifiedIt's been 10 days
Full text (crm_email_templates/flows/Flow-ABSENCE_Day10_Email.html)
CustomerBOOM E1 — 30-day check-inUnverifiedHow's the game going, First Name?
Full text (crm_email_templates/flows/BOOM-E1-30d_Check-In.html)
CustomerBOOM E2 — 60-day reason-matched follow-upUnverifiedStill true for you?
Full text (crm_email_templates/flows/BOOM-E2-60d_Reason-Matched.html)
CustomerBOOM E3 — 90-day final inviteUnverifiedYour TrackMan history is still here
Full text (crm_email_templates/flows/BOOM-E3-90d_Final-Invite.html)
CustomerReonboard welcome-backUnverifiedGood to see you back in the bay
Full text (crm_email_templates/SprintJ/REONBOARD.html)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Is a specific member currently flagged at-risk? | Contacts › the member's record › Last_ATRISK_Alert and Absence_Stage fields | A recent date in Last_ATRISK_Alert and/or a non-zero Absence_Stage means the flow has them in view. |
| Where is a churned member in the win-back drip? | the member's PauseCancel_Request record (Cancel type) › Boom_Stage (0-3) and Boom_Stage_Changed | Stage 3 means all three win-back emails have gone out for that cancellation. |
| Did a returning member get the welcome-back note? | Contacts › the member's record › Reonboard_Last_Sent | A date here means the one-time welcome-back email was queued for that return booking. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| at-risk staff digest | Zoho CRM Setup › Automation › Schedules › atrisk_scan | the daily leadership digest and the Last_ATRISK_Alert stamp |
| absence ladder | Zoho CRM Setup › Automation › Schedules › sfaabsenceladder | the day-10 email and all Absence_Stage progression |
| churn win-back drip | Zoho CRM Setup › Automation › Schedules › sfaBoomSweep_Daily | the 30/60/90-day BOOM emails and Boom_Stage progression |
| welcome-back note | Zoho CRM Setup › Automation › Schedules › sfaReonboardWelcome | the one-time returning-member email |
Good to know
Coach and card checks apply throughout
Every step in this flow (absence ladder, BOOM, reonboard) skips a contact who's mid-onboarding (<30 days), in card-update dunning, or has a card expiring within 10 days — the same suppression logic is repeated in each function rather than shared.
A 4-day frequency cap ties the whole nurture surface together
Last_Nurture_Sent is a shared field: once any nurture email fires for a contact (absence, BOOM, RE-L/RE-P, etc.) a 4-day cooldown blocks other nurture sends to the same person.
Feeder data for the at-risk scan
A nightly refresh (gmDailyRefresh) keeps the session/credit dates on Contacts current, which is what the at-risk scan and absence ladder read Last_Activity_Date from.
Rebooking nudge is a separate, related flow
The 2-5 day post-lesson "book your next session" nudge (sfaNextbookNudge) is covered in the lesson-booking flow, not here — it's triggered by a completed lesson, not by extended absence.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (8)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
atrisk_scan6296422000046175051 | schedule | Live last run 2026-09-23 | daily 08:00 Asia/Dubai Lifecycle_Status in Member/Beginner Member/6 Month Member/Junior Member (paged, 200 per page), with a live Membership (plan type from Onboarding_Route, or from Plan_Code when the route is blank: SFPM/SFPM997/SFPMMonth/PPMM/PPMonth = Practice, SUMMER = unclear, every other code = Coaching); paused members skipped (Pause_Date to Pause_Stop_Date); max and the test fixture skipped. Bookings counted = past, not Cancelled and not Not Completed (booked, not attended). Drifting = 10-20 days since last past booking with no upcoming booking, or a 30d-vs-prior-30d drop of 40%+ with baseline of 4+ bookings and 3 or fewer recent. Lapsed = 21+ days since last past booking with no upcoming booking, listed in its own section. PAYG (Client + active flag) still unpaged. Last_ATRISK_Alert cooldown of 7 days (bypassed only in testMode). [code] | Builds one HTML digest of every flagged contact (grouped Coaching / Practice-only / Plan Unclear / PAYG-credits / PAYG-no-credits, capped at 40 shown) and sends it via CRM send_mail to max/akash/vic/lucy; stamps Last_ATRISK_Alert on each flagged contact. | Zoho CRM Setup › Automation › Schedules crm_functions_live/functions/atrisk_scan.deluge |
sfaAbsenceLadder6296422000046337624 | schedule | Patched last run 2026-09-23 | daily 16:00 Asia/Dubai Lifecycle_Status = Member/Beginner Member/6 Month Member/Junior Member (paged, all pages); skips paused contacts, contacts with no live membership, and anyone with an upcoming booking; last visit = last past booking (future dates ignored); Absence_Stage resets to 0 if days_absent < 5. | Day 10-13 only: queues the Day-10 email (template 6296422000046337602) through send_mail, gated by onboarding/dunning/card-expiry/4-day-frequency-cap, max 25 sends per run, stamps Absence_Stage=2 only after a successful send. Day 5 (WhatsApp) and Day 14 (Member Success task) are counted in the run report but not acted on and no longer stamp a stage. Run report goes to max@ every run. | Zoho CRM Setup › Automation › Schedules crm_functions_live/functions/sfaabsenceladder.deluge |
sfaBoomSweep6296422000047420271 | schedule | Active last run 2026-09-02 (arch | daily 10:00 Asia/Dubai Scans PauseCancel_Request where Request_Type=Cancel and the linked Contact's Lifecycle_Status=Churned Member; Boom_Stage < 3; skips if Winback_Started is set and under 21 days old; stage thresholds at 30/60/90 days since the Cancel request's Created_Time. | Writes a reason-matched copy line (Boom_Reason_Line / Boom_Reason_Line_E2) onto the PauseCancel_Request based on the stated cancellation reason, sends the matching BOOM-E1/E2/E3 template via send_mail (includes org_email:true), advances Boom_Stage and stamps Boom_Stage_Changed, and on the first send stamps Winback_Started on the Contact. | Zoho CRM Setup › Automation › Schedules (sfaBoomSweep_Daily) $HOME/arch/crm_deluge_source/sfaboomsweep.deluge (function id 1446733000000698001) |
sfaReonboardWelcome6296422000047944146 | schedule | Live last run 2026-09-22 | daily 14:00 Asia/Dubai Looks at today's non-cancelled Bookings; finds each customer's most recent prior non-cancelled booking; requires a 60+ day gap; requires no Reonboard email in the last 90 days; same onboarding/dunning/card-expiry checks as the rest of the flow. | Sends template 6296422000047944117 via send_mail, stamps Reonboard_Last_Sent, and resets Winback_Started and Absence_Stage to 0 so the contact re-enters the normal flow. | Zoho CRM Setup › Automation › Schedules crm_functions_live/functions/sfaReonboardWelcome.deluge |
gmDailyRefresh6296422000045075189 | schedule | Active last run 2026-09-02 (arch | nightly 03:00 n/a — bulk refresh, not contact-filtered. | Refreshes session/credit dates on Contacts overnight; this is the data the at-risk scan and absence ladder read Last_Activity_Date from. Feeder step, not customer-facing. | Zoho CRM Setup › Automation › Schedules $HOME/arch/crm_deluge_source/gmdailyrefresh.deluge (function id 1446733000000601001) |
sfaRepermBsu6296422000047418001 | schedule | Not last run 2026-09-01 (arch | daily 16:15 Asia/Dubai Sunset_Stage > 0, or 90+ days inactive and not opted out; skips paused contacts, contacts mid absence-ladder stage 1/2, contacts in their first 7 days after a PAYG first purchase, Leads/Prospects, and anyone without a populated Winback_Started at least 60 days old. | Designed to run REPERM (still-subscribed check) then BSU (final-touch) emails and eventually suppress (Sunset_Stage=5, Email_Opt_Out=true). testMode is hardcoded true in the function body, so every real write is skipped and every email routes to the internal test address instead of the contact. | Zoho CRM Setup › Automation › Schedules crm_functions_live/functions/sfaRepermBsu.deluge |
Inactive Retention (B5)6296422000045282145 | workflow rule | Inactive last run 2026-09-09T15:00 | date/datetime — 21 days after Last_Activity_Date Member or PAYG branch; onboarding/nurture-cooldown/card-expiry/dunning gates. | Sends a Retention E1 email instantly and a Retention E2 email 7 days later, per member/PAYG branch. | Zoho CRM Setup › Automation › Workflow Rules › Contacts n/a — CRM workflow rule, no Deluge source |
B8 Branch M - Churned Member Winback6296422000045681094 | workflow rule | Inactive last run 2026-08-09T13:30 | field update — Lifecycle_Status becomes Churned Member Coach populated or not; Winback_Started empty; card/dunning/onboarding/nurture-cooldown gates. | Sends a 3-step email sequence (Warm Reconnect instant, Value Reminder at +7d, Free Evaluation Offer at +21d) branched by whether the member had a coach. | Zoho CRM Setup › Automation › Workflow Rules › Contacts n/a — CRM workflow rule, no Deluge source |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Contacts | Last_ATRISK_Alert | Date last flagged by the at-risk scan; drives its 7-day cooldown. | atrisk_scan |
| Contacts | Absence_Stage | 0=not absent/reset, 1=day-5 stage, 2=day-10 stage (email sent), 3=day-14 stage. | sfaAbsenceLadder |
| PauseCancel_Request | Boom_Stage | 0-3 progress through the churn win-back drip. | sfaBoomSweep |
| PauseCancel_Request | Boom_Stage_Changed | Timestamp of the last Boom_Stage advance. | sfaBoomSweep |
| PauseCancel_Request | Boom_Reason_Line / Boom_Reason_Line_E2 | Reason-matched copy line inserted into the BOOM email based on the stated cancellation reason. | sfaBoomSweep |
| Contacts | Winback_Started | Date the churn win-back drip first fired for this contact; also gates REPERM/BSU eligibility (needs 60+ days old). | sfaBoomSweep (set), sfaReonboardWelcome (cleared on return) |
| Contacts | Reonboard_Last_Sent | Date of the one-time welcome-back email; blocks a repeat within 90 days. | sfaReonboardWelcome |
| Contacts | Sunset_Stage | 0=cold-eligible, 1/2=REPERM sent, 3/4=BSU sent, 5=suppressed (Email_Opt_Out, never deleted). | sfaRepermBsu (currently inert — testMode hardcoded true) |
| Contacts | Last_Nurture_Sent | Shared 4-day frequency-cap timestamp checked by every nurture automation on the account (absence ladder, BOOM, RE-L/RE-P, etc.). | shared across nurture functions |
IDs and references
| What | Value |
|---|---|
| atrisk_scan schedule | 6296422000046175051 |
| sfaAbsenceLadder schedule | 6296422000046337624 |
| sfaBoomSweep_Daily schedule | 6296422000047420271 |
| sfaReonboardWelcome schedule | 6296422000047944146 |
| gmDailyRefresh schedule | 6296422000045075189 |
| sfaRepermBsu schedule | 6296422000047418001 |
| Inactive Retention (B5) workflow rule | 6296422000045282145 |
| B8 Branch M workflow rule | 6296422000045681094 |
All flows › Pause or cancel
When a member pauses, resumes or cancels their membership
A member's pause/cancel form flows through Zoho Billing into GolfManager and CRM, with pause-day tracking and a staff save-window alert.
- Starts when
- A member submits the /pause or /cancel form on swingfitacademies.com (or Member Success enters the request for them in the Zoho Creator 'Pause' app / directly in Billing).
- Covers
- Covers the member-initiated pause/cancel/resume path from the swingfitacademies.com forms and the Zoho Creator Pause app, through Zoho Billing and GolfManager, the CRM PauseCancel_Request save-window pipeline, and the customer/staff emails involved. Does not cover the win-back/rejoin journey in detail (pointer only), individual booking cancellations (separate trace), or Zoho Forms' own internal configuration (no live tool available to inspect it).
- Systems
- Zoho Forms, Zoho Flow, Zoho Billing, GolfManager, Zoho CRM, Zoho Creator, Zoho Cliq, Gmail/Website
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Form submittedZoho Forms
Member submits a pause or cancel request
Verified liveThe member fills the pause or cancel form. This creates a record in the Zoho Creator 'Pause' app (a staff-visible board, separate from CRM) and separately posts to Zoho Billing via Zoho Flow. A matching PauseCancel_Request record is also created in CRM for the same request.
See itZoho Creator 'Golf Manager' app -> Pause records; CRM -> PauseCancel Request module, sorted by Created Time. - T+0..2sCreator staff alertZoho Flow
Staff get a Cliq ping for the new pause/cancel entry
From codeTwo Flows in the 'Zoho Creator Pause' folder (
Cliq Notification,Cliq Notification Cancel) fire on 'record created' in the Creator Pause app and post a message to a Cliq channel so staff see the new request immediately.See itCliq channel used by the Pause app (folder: Zoho Creator Pause). - T+0..5sPushed to BillingZoho Flow
The form's webhook pushes the request into Zoho Billing
From codeZBilling_SubscriptionPause_ZohoFormsorZBilling_SubscriptionCancel_ZohoForms(folder: Zoho Forms - Zoho Billings/Creator) looks the member up in Zoho Billing by email, checking the DIFC org (872210045) first and then Studio City (866469739). For cancellations, the code calls Billing's cancel endpoint withcancel_at_end:false. In practice the cancellation is not made on the request date: the request is held in SwingFIT's Creator app, which makes the Billing cancellation the day before the effective date (next step). Pause adds the requested days to a running lifetime total stored on a Billing subscription custom field (id 5800147000018689006); if that total is 56 days or under it calls Billing's pause endpoint and updates the field; if it's over 56, the pause is declined and a 'Pause Alert' email is sent to the member directly from this Flow function.See itZoho Billing -> Customers -> subscription -> Status/History tab. - day before effective dateScheduled cancelZoho Creator
The Creator app cancels the subscription in Billing the day before it takes effect
UnverifiedCancel requests are stored in SwingFIT's own Zoho Creator app. The request is also copied into CRM (PauseCancel_Request) so the team can see a request was made, but the CRM copy does not cancel anything. The Creator app makes the actual cancellation in Zoho Billing the day before the cancellation date, so no further charge is taken. Until then the subscription correctly shows as live in Billing, and the member keeps full access.
See itZoho Creator app -> pause/cancel records for the request and its date. From the day before the effective date: Zoho Billing -> subscription -> History shows the cancellation. - T+2..10sBilling status change fires GolfManager syncZoho Billing
The subscription status change fires the Billing-to-GolfManager Flows
From codeZoho Billing's own status-change webhooks trigger flows in the 'Zoho Billing - Golf Manager' folder.
PauseSubscriptionZGOLF(function PauseSubscription) andCancelSubscriptionZGOLF(function CancelSubscription) both look up the subscription's 'GolfManager Membership ID' custom field and act on GolfManager'ssubscriptionCustomerrecord for that member.New_Resume_ReactivateMembershipZGOLFhandles new subscriptions, resumes and reactivations by looking up the item's membership-type custom field, finding or creating the GolfManager customer, and creating a subscriptionCustomer record.RestofSubscriptionStatus_Creatormirrors the plain-English status (Active/Paused/Cancelled/Non Renewing/Future) onto the matching record in the Creator 'All_Memberships' report for the staff dashboard.- PauseUnverifiedT+2..10s
PauseSubscription is designed to pause the member's GolfManager membership when the Billing subscription's cancel_at_end/cancelled_at fields show a pause rather than a scheduled cancellation.
- Immediate cancelVerified liveT+2..10s
CancelSubscription removes the GolfManager subscriptionCustomer record when the Billing subscription status isn't 'non_renewing'.
- Scheduled (non_renewing) cancelFrom codeT+2..10s
If the Billing status is 'non_renewing', CancelSubscription instead PATCHes the existing membership's end date rather than deleting it.
- Resume / reactivate / newUnverifiedvaries
New_Resume_ReactivateMembershipZGOLF creates a subscriptionCustomer record for a new, resumed or reactivated membership.
See itGolfManager back office -> Customer -> Memberships tab. - T+2..10sLifecycle flip on cancelZoho Flow
Cancelled members get flipped to 'Churned Member' in CRM
From codeA separate Billing webhook (folder: Zoho Billing - Zoho CRM/Cliq) runs
UpdateLifecycle_ChurnedMember, which looks up the CRM Contact by the Billing customer's email and, only if their Lifecycle_Status currently reads 'Member', updates it to 'Churned Member'. Related flows do the equivalent for new/resumed members.See itContacts -> Lifecycle_Status field. - T+0..1mCRM save-window pipeline startsZoho CRM
The PauseCancel_Request record drives the CRM-side pause tracking and save attempt
UnverifiedWorkflow rule
PauseCancel Request(create/edit) is designed to run functionpausecancelrequest: it reads the linked Membership's status, computes a rolling pause allowance for the member (56 days per 365-day cycle measured from the membership's Start_Date, based on their PauseCancel_Request history), and writes Membership_Status/Cancellation_Date/Pause_Date/Pause_Stop_Date/Day_Available_to_Pause onto the Contact record (passing the workflow-trigger option so downstream field-update rules fire), then stamps the live numbers back onto the request itself.See itContacts record -> Membership_Status, Day_Available_to_Pause; PauseCancel_Request record -> Pause_Days_Remaining, Pause_Cycle_Reset_Date. - nightly, within 3 days of pause start / within 7 days of pause endpause emailsZoho CRM
The member gets a 'pause started' email, then a 'pause ending' reminder
From codeA nightly pause sweep checks every open pause request whose membership is paused in Billing. Within 3 days of the pause starting it sends the 'pause started' email, and within 7 days of the pause ending it sends the 'pause ending' reminder, both from info@ with Member Success copied. Each email is marked sent on the request only once it has actually gone out, so a missed send is retried the next night. Pauses that are already over are closed off without an email.
See itPauseCancel_Request record -> P1_Sent / P2_Sent dates and its Emails list. - T+1..2mDownstream Contact syncZoho CRM
Contact status change cleans up stale credits on cancellation
Verified liveWhen Membership_Status changes to a cancelled-like value, field-update rules
B9a Cancellation Sync - Membership Status CoreandB9b ... Creditssync Lifecycle_Status, Customer_Type, Credit_Balance and the per-type credit balances, so stale credit data stops driving reminder emails to churned members.See itContacts record -> Lifecycle_Status, Credit_Balance and the per-type credit fields. - designed: T+0..1m on createCoach/MS owner stamped + save-window emailZoho CRM
The accountable coach and Member Success owner get stamped and emailed to try a save
UnverifiedWorkflow rule
sfaCancellationStamp(create; fires when Request_Type=Cancel or Cancellation_Date is set) is designed to run functionsfacancellationstamp: it finds the member's most recent non-cancelled coaching booking to identify the coach, finds the Membership record's Owner (or the Contact's Sales_Person) as the MS owner, stamps both onto the request with an outcome-form link, and sends an internal 'save window' email to that coach + MS owner (cc max/lucy/akash) via the CRM email-template API.See itPauseCancel_Request record -> Stamped_Coach, Stamped_Coach_Email, MS_Owner, MS_Owner_Email fields. - designed: every 30 min; T+24h and T+48hNudge / escalate if no save loggedZoho CRM
A sweep is designed to catch missed stamps and chase an unresolved cancel
UnverifiedsfaCancellationSweepis designed to re-run the stamp step for any Cancel request the create-trigger rule missed (Creator/API-created records can bypass it), then send a 24-hour nudge to the coach+MS owner and a 48-hour escalation to max/lucy/akash if Save_Attempt_Logged is still false.See itPauseCancel_Request record -> Nudged, Escalated, Save_Attempt_Logged fields. - T+0..few minCustomer cancel confirmationWebsite
The member gets a 'Cancel Request Confirmation' email
Verified liveA branded confirmation (subject 'Cancel Request Confirmation', from info@swingfitacademies.com, cc akash@/bijoy@yelobase.com/max@) tells the member their monthly or annual membership is on notice and states the effective end date. The exact system sending it was not located in the CRM or Zoho Flow Deluge source checked in this pass, so it is most likely a native Zoho Forms notification rather than a CRM or Flow action.
See itMember's inbox, subject 'Cancel Request Confirmation'. - daily 02:00Nightly safety-net syncZoho CRM
A nightly batch re-syncs Billing memberships into CRM regardless of whether the real-time Flows worked
From codeThe 'Billing Memberships Daily Sync' schedule re-pulls Billing subscription data into CRM Memberships nightly, independent of the real-time webhooks above.
See itSchedules -> Billing Memberships Daily Sync -> last run.
Emails and messages
CustomerCancel Request ConfirmationVerified liveCancel Request Confirmation
Full text (crm_email_templates/flows/J15a_Membership-Cancellation-Monthly.html)
CustomerPause Alert (pause declined, 56-day cap reached)UnverifiedPause Alert
Full text (flow_deluge_source/ZBilling_SubscriptionPause_ZForms.deluge)
TeamSave window open (internal)UnverifiedSave window: PauseCancel_Request.Player cancelled
Full text (crm_email_templates/cancellation-followup-email-template.html)
Team24h coach/MS nudge (internal)Unverified(reminder template, subject not inspected)
Full text (crm_email_templates/cancellation-nudge-email-template.html)
Team48h escalation (internal)Unverified(escalation template, subject not inspected)
Full text (crm_email_templates/cancellation-escalation-email-template.html)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did the member's pause or cancel actually reach Zoho Billing? | Zoho Billing -> Customers -> subscription -> Status/History tab | Status flips to Paused / Cancelled / Non-Renewing within seconds of the form submission. |
| Will a cancel request actually stop the billing? | Zoho Creator app (pause/cancel records); then Zoho Billing -> subscription -> History | The request is in the Creator app with its cancellation date, and Billing shows the subscription cancelled by the day before that date. Billing showing it as live before then is normal. |
| Did GolfManager pick it up? | GolfManager back office -> Customer -> Memberships tab | The membership record shows an inactive/paused state (or is removed for an immediate cancellation) matching the Billing status. |
| Is anyone trying to save this member before they leave? | CRM -> PauseCancel_Request record -> Stamped_Coach / MS_Owner / Save_Attempt_Logged fields | Stamped_Coach and MS_Owner filled in within minutes of a Cancel request being created, and Save_Attempt_Logged set once someone acts. |
| Did the customer get a correct confirmation? | Search the member's inbox / max@ cc for 'Cancel Request Confirmation' | No literal bracket placeholder text anywhere in the email, including hidden preview text. |
| How many pause days does this member have left? | Contacts.Day_Available_to_Pause (CRM) vs. the Billing subscription's pause-days custom field | The two numbers should agree; they're computed independently in CRM and Billing and can differ. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Members reaching Billing directly from the forms | Disable the /pause and /cancel Zoho Forms, or disable Flows ZBilling_SubscriptionPause_ZohoForms / ZBilling_SubscriptionCancel_ZohoForms (folder: Zoho Forms - Zoho Billings/Creator) | The actual pause/cancel action in Zoho Billing (and everything downstream of it, since Billing status never changes). |
| GolfManager membership create/update/delete on Billing status change | Disable Flows PauseSubscriptionZGOLF / CancelSubscriptionZGOLF (folder: Zoho Billing - Golf Manager) | Only the GolfManager side-effect; Billing itself still shows the member as paused/cancelled. |
| The internal save-window email + nudge/escalation chain | Deactivate CRM workflow rule sfaCancellationStamp and leave sfaCancellationSweep unscheduled | Only the coach/MS-owner emails and the stamped fields; the pause-day tracking (pausecancelrequest) and B9a/B9b credit sync keep running. |
| The auto churn-lifecycle flip | Disable Flow 'Update Lifecycle Churned Member' (folder: Zoho Billing - Zoho CRM/Cliq) | Contacts.Lifecycle_Status no longer auto-flips to 'Churned Member' on a Billing cancellation webhook. |
Good to know
Two independent 56-day pause counters
CRM computes a rolling pause allowance per 365-day cycle measured from the membership's Start_Date (resets every year). Zoho Billing separately tracks a lifetime running total on a subscription custom field that never resets. They are not synced, so the two 'days remaining' numbers can disagree.
Org lookup order for Billing
The pause/cancel Flow functions search DIFC (872210045) before Studio City (866469739) by matching the member's email against Billing customers; a member's Home_Location on their CRM Contact doesn't determine which org is checked.
GolfManager supports pausing natively
The subscriptionCustomer model has a built-in active true/false flag and an end date field, so a membership can be marked inactive or given an end date without deleting the record.
Creator-form records can bypass the CRM create-trigger rule
PauseCancel_Request records created through the Zoho Creator Pause app (rather than directly via CRM) don't reliably fire the create-trigger workflow rule, which is why sfaCancellationStamp was designed to also be picked up by the periodic sweep.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (17)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Cliq Notification / Cliq Notification Cancellink_name cliq_notification / cliq_notification_cancel | flow | Active | record created in the Zoho Creator 'Pause' app none - fires on every new Pause/Cancel record | Posts a message to a Cliq channel so staff see the new pause/cancel request immediately. | Zoho Flow > folder 'Zoho Creator Pause' flow_deluge_source (Cliq post step is inline in the Flow, no separate custom function) |
ZBilling_SubscriptionPause_ZohoFormslink_name zbilling_subscriptionpause_zohoforms | flow | Active | the /pause form webhook looks the member up in Billing by email, DIFC org (872210045) checked before Studio City (866469739); cumulative pause-days custom field must be <= 56 to proceed | Adds the requested days to Billing subscription custom field 5800147000018689006 (a lifetime running total that never resets); if the new total is <=56 calls Billing's pause endpoint and updates the field; if over 56, declines the pause and sends the 'Pause Alert' email directly from this Flow's own Zoho Mail connection. | Zoho Flow > folder 'Zoho Forms - Zoho Billings/Creator' flow_deluge_source/ZBilling_SubscriptionPause_ZForms.deluge |
SwingFIT Creator app - scheduled cancellationnot captured | creator | Active | the day before the request's cancellation date cancel requests stored in the app | Cancels the member's Zoho Billing subscription the day before the cancellation takes effect, so the next charge is not taken. The CRM PauseCancel_Request record is a visibility copy only and does not trigger the cancellation. | Zoho Creator (SwingFIT's own app, pause/cancel records) not read: Creator source is not in the AI OS and no Creator connector is available to sessions |
ZBilling_SubscriptionCancel_ZohoFormslink_name zbilling_subscriptioncancel_zohoforms | flow | Active | the /cancel form webhook looks the member up in Billing by email, DIFC before Studio City | Calls Billing's cancel endpoint with cancel_at_end hardcoded to false, ending the subscription immediately regardless of any notice period quoted to the member. | Zoho Flow > folder 'Zoho Forms - Zoho Billings/Creator' flow_deluge_source/ZBilling_SubscriptionCancel_ZohoForms.deluge |
PauseSubscriptionZGOLF (function PauseSubscription)link_name pausesubscription | flow | Active | Zoho Billing subscription status-change webhook only checks the subscription's cancel_at_end/cancelled_at fields | Looks up the subscription's 'GolfManager Membership ID' custom field and DELETEs the matching GolfManager subscriptionCustomer record outright whenever cancel_at_end isn't true - there is no distinct pause branch, so a pause and an immediate cancel currently do the same destructive thing on the GolfManager side. | Zoho Flow > folder 'Zoho Billing - Golf Manager' flow_deluge_source/PauseSubscription.deluge |
CancelSubscriptionZGOLF (function CancelSubscription)link_name cancelsubscription | flow | Active | Zoho Billing subscription status-change webhook branches on whether the Billing subscription status is 'non_renewing' | Deletes the GolfManager subscriptionCustomer record for an immediate cancel; for a scheduled (non_renewing) cancel it instead PATCHes the existing membership's end date rather than deleting it. | Zoho Flow > folder 'Zoho Billing - Golf Manager' flow_deluge_source/CancelSubscription.deluge |
New_Resume_ReactivateMembershipZGOLF (function New_Resume_Reactivate_SubToGM)link_name reactivatemembershipzgolf | flow | Active | Zoho Billing webhook for a new subscription, resume, or reactivation looks up the item's membership-type custom field | Finds or creates the GolfManager customer and creates a subscriptionCustomer record. Its own duplicate-prevention block (an existing-GM-membership-ID lookup meant to return early with the comment 'DO NOT CREATE GM MEMBERSHIP TWICE') is entirely commented out, so it always POSTs a brand-new membership record on every fire, whether or not one already exists. | Zoho Flow > folder 'Zoho Billing - Golf Manager' flow_deluge_source/New_Resume_Reactivate_SubToGM.deluge |
RestofSubscriptionStatus_Creatorlink_name restofsubscriptionstatus_creator | flow | Active | Zoho Billing subscription status-change webhook none | Mirrors the plain-English status (Active/Paused/Cancelled/Non Renewing/Future) onto the matching record in the Zoho Creator 'All_Memberships' report, purely for the staff dashboard - no downstream effect on Billing, CRM or GolfManager. | Zoho Flow > folder 'Commission App - Golf Manager - Zoho' flow_deluge_source (Creator write step inline in the Flow) |
Update Lifecycle Churned Member (function UpdateLifecycle_ChurnedMember)link_name update_lifecycle_churned_member | flow | Active | Zoho Billing subscription-cancelled webhook only updates the Contact if their current Lifecycle_Status reads 'Member' | Looks up the CRM Contact by the Billing customer's email and flips Lifecycle_Status to 'Churned Member'. | Zoho Flow > folder 'Zoho Billing - Zoho CRM/ Cliq' flow_deluge_source/UpdateLifecycle_ChurnedMember.deluge |
PauseCancel Request6296422000045556118 | workflow rule | Active last run 2026-09-01T06:54 | create or edit (repeat) of a PauseCancel_Request record none on the rule itself | Runs function pausecancelrequest: reads the linked Membership's status, computes a rolling 56-day-per-365-day pause allowance measured from the membership's Start_Date using the member's PauseCancel_Request history, writes Membership_Status/Cancellation_Date/Pause_Date/Pause_Stop_Date/Day_Available_to_Pause onto the Contact (passing the workflow-trigger option so downstream field-update rules fire), then stamps Pause_Days_Remaining/Pause_Cycle_Reset_Date back onto the request. | Zoho CRM > Setup > Automation > Workflow Rules > module PauseCancel_Request crm_deluge_source/pausecancelrequest.deluge |
B9a Cancellation Sync - Membership Status Core6296422000048352026 | workflow rule | Active last run 2026-09-01T06:54 | field_update on Contacts.Membership_Status Membership_Status equals cancelled, cancelled_from_dunning, or expired | Field-updates Lifecycle_Status to Churned Member, Customer_Type to Not Active, and zeroes Credit_Balance, Regular_Coaching_Credit_Balance and Practice_Credit_Balance. | Zoho CRM > Setup > Automation > Workflow Rules > module Contacts field-update actions only, no Deluge function |
B9b Cancellation Sync - Membership Status Credits6296422000048450002 | workflow rule | Active last run 2026-09-01T06:54 | field_update on Contacts.Membership_Status Membership_Status equals cancelled, cancelled_from_dunning, or expired | Zeroes the remaining per-type credit fields: Fitness, Junior, Member Lesson, Member Coaching credit balances. | Zoho CRM > Setup > Automation > Workflow Rules > module Contacts field-update actions only, no Deluge function |
sfaCancellationStamp6296422000045723141 | workflow rule | Active last run 2026-09-01T07:06 | create Request_Type equals 'Cancel' OR Cancellation_Date is not empty | Runs function sfacancellationstamp: finds the member's most recent non-cancelled coaching booking to identify the accountable coach, finds the Membership record's Owner (or the Contact's Sales_Person) as the Member Success owner, stamps both plus an outcome-form link onto the request, and sends the 'save window' email (template 6296422000045733003) to that coach + MS owner, cc max/lucy/akash. | Zoho CRM > Setup > Automation > Workflow Rules > module PauseCancel_Request crm_functions_live/functions/sfacancellationstamp.deluge |
sfaCancellationSweepnot found on a live schedule list this pass (function exists, no confirmed schedule id) | schedule | Function | designed for every 30 minutes any Cancel-type PauseCancel_Request where Save_Attempt_Logged is still false | Re-runs the stamp step for any Cancel request the create-trigger rule missed (Creator/API-created records can bypass it), then sends a 24-hour nudge (template 6296422000045733001) and a 48-hour escalation (template 6296422000045974078) to the coach/MS owner and max/lucy/akash respectively. | intended: Zoho CRM > Setup > Automation > Schedules crm_deluge_source/sfacancellationsweep.deluge |
Billing Memberships Daily Sync6296422000045556008 | schedule | Active last run 2026-09-02T02:04 | daily 02:00 Dubai none - re-pulls every subscription from both Billing orgs | Re-syncs Billing subscription status/balance into CRM Memberships nightly, independent of the real-time webhook Flows above, as a safety net that runs regardless of whether those Flows fired earlier in the day. | Zoho CRM > Setup > Automation > Schedules crm_deluge_source/billing_memberships_daily_sync.deluge |
ResumeSubscriptionZGOLF (function ResumeSubscription) — deadlink_name resumesubscription | flow | Inactive | n/a - disabled n/a | Near-identical logic to New_Resume_ReactivateMembershipZGOLF, which now handles new/resume/reactivate together; this older Flow is fully superseded. | Zoho Flow > folder 'Zoho Billing - Golf Manager' flow_deluge_source/ResumeSubscription.deluge |
pausestatussweep (function pausesweep / sfaPauseLifecycleSweep)see crm_functions_live/INDEX.md | schedule | Active | daily (evening, ~20:00 Dubai) Open PauseCancel_Request records with a start and stop date, where P1_Sent or P2_Sent is still blank; only when the member's Membership is in 'paused' status in Billing. | Recomputes pause allowance (56 days per 365-day cycle) onto the request and the Contact (Day_Available_to_Pause, Membership_Status, Pause_Date, Pause_Stop_Date). Sends P1 'pause started' (template 6296422000046223071) within 3 days of the pause start and P2 'pause ending' (template 6296422000046223074) within 7 days of the stop date, from info@ with org_email, cc max@. P1_Sent/P2_Sent are stamped only after a confirmed send, so a failed send retries the next night inside its window. Requests whose pause is already over are retired without sending. One summary alert to max@ per run if any send fails. | Zoho CRM > Setup > Automation > Schedules crm_functions_live/functions/pausesweep.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Billing subscription (custom field) | id 5800147000018689006 | Lifetime running total of pause days ever taken on this subscription (never resets) | ZBilling_SubscriptionPause_ZohoForms |
| Contacts | Membership_Status | CRM-side status label (e.g. active/paused/cancelled) distinct from Billing's own status string | pausecancelrequest |
| Contacts | Cancellation_Date / Pause_Date / Pause_Stop_Date | Dates driving the CRM-side pause/cancel timeline | pausecancelrequest |
| Contacts | Day_Available_to_Pause | Remaining pause-day allowance on a 365-day cycle measured from the membership's Start_Date | pausecancelrequest |
| PauseCancel_Request | Pause_Days_Remaining / Pause_Cycle_Reset_Date | Live numbers stamped back onto the request at the moment it's processed | pausecancelrequest |
| PauseCancel_Request | Stamped_Coach / Stamped_Coach_Email / MS_Owner / MS_Owner_Email | Accountable coach and Member Success owner identified for the save attempt | sfacancellationstamp |
| PauseCancel_Request | Nudged / Escalated / Save_Attempt_Logged | Tracks whether the 24h/48h chase fired and whether staff logged an outcome | sfacancellationsweep |
| Contacts | Lifecycle_Status / Customer_Type / Credit_Balance and per-type credit fields | Cleared/flipped so stale credit data stops driving reminder emails to churned members | B9a Cancellation Sync - Membership Status Core / B9b ... Credits |
| Billing subscription (custom field) | GolfManager Membership ID | Links a Billing subscription to its GolfManager subscriptionCustomer record | read by PauseSubscription/CancelSubscription; written when the GolfManager membership is first created |
Full email text
Membership Pause Confirmation (design source — no send-step found for this pass's live path)Your SwingFIT membership is paused - [PAUSE_START_DATE] to [PAUSE_END_DATE]
T18 Subscription Paused (Billing template library — send-step not confirmed live)Your SwingFIT membership is paused
T19 Subscription Cancelled (Billing template library — send-step not confirmed live)Your SwingFIT membership has been cancelled
IDs and references
| What | Value |
|---|---|
| Zoho Books org — Studio City | 866469739 |
| Zoho Books org — DIFC | 872210045 |
| Billing subscription custom field — lifetime pause-days total | 5800147000018689006 |
| CRM email template — save window open | 6296422000045733003 |
| CRM email template — 24h nudge | 6296422000045733001 |
| CRM email template — 48h escalation | 6296422000045974078 |
| CRM workflow rule — PauseCancel Request | 6296422000045556118 |
| CRM workflow rule — sfaCancellationStamp | 6296422000045723141 |
All flows › Reviews
How we ask for and collect reviews
A satisfied-member moment is turned into a Google review through an in-person QR-code ask and a coach script -- there is no automated email or WhatsApp send in this flow today.
- Starts when
- A member hits a milestone, beats a benchmark, or has a clearly great session -- a staff member or coach notices the moment and makes the ask on the spot.
- Covers
- How SwingFIT generates and collects Google reviews (the Review Flywheel): the trigger moment, the ask itself, where the review lands, response ownership, and how it's measured against a baseline. Does not cover in-app NPS or post-session feedback capture, which is a separate, still-orphaned workstream.
- Systems
- Zoho CRM, WhatsApp, Website
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- n/aThe momentWebsite
The ask is timed to a real moment of satisfaction, not sent cold
Verified liveBenchmarks and exit standards already tracked in the coaching system surface the 'earned it' moment (a level up, a benchmark beaten). A coach or staff member also uses their own judgment when a member is visibly delighted after a session. Member events (clinics, group classes) are a related moment -- a room of satisfied members at once.
See itCoaching system benchmarks/exit standards; Member Events calendar. - n/aThe askWebsite
A QR code and a one-line coach script, not a system-sent message
Verified liveA QR code at the bay/desk at each site (Studio City and DIFC) links straight to that location's own Google review form. Staff use a short, fixed script: "Great session. That number's earned. If you've got a minute, leave us a Google review and tell people what the data's done for your game. The QR by the screen takes you straight there."
See itQR posters at the bay/desk, Studio City and DIFC. - n/aThe review landsWebsite
Each site's reviews land on that site's own Google Business Profile
Verified liveStudio City and DIFC each have their own Google Business Profile and their own review short-link, so a review always lands on the profile for the location the member actually visited.
See itGoogle Business Profile, Studio City and DIFC listings. - n/aResponseStaff
Every review gets a reply, owned by one person
UnverifiedMax replies to every review within 48 hours. Negative or mixed reviews use Founder Voice: first person, own the issue in line one, offer a fix in public, take details private -- never defensive, never policy-quoting.
See itGoogle Business Profile > Reviews tab, reply timestamps. - n/aThank & recognizeStaff
Members are thanked without any condition attached; staff recognition is still undecided
UnverifiedMembers who leave a review are thanked unconditionally -- reviewing is never rewarded and never gated by sentiment, in line with Google's review policies. What, if anything, recognizes staff for the reviews they helped generate is still an open call.
See itn/a (a design principle, not a system). - n/aMeasurementStaff
Review count is tracked weekly against a frozen baseline
Verified liveThe starting point (Studio City 5.0 stars / 277 reviews, DIFC 4.8 stars / 53 reviews, combined 330) was captured from Google Business Profile and frozen as the baseline this flow is measured against, with a target of 350 combined reviews.
See itGoogle Business Profile review counts vs the frozen baseline record. - n/aPlanned follow-up askWhatsApp
A message-based follow-up ask after a milestone is designed but not yet built
UnverifiedA planned second ask -- a post-milestone email or WhatsApp message carrying the review link -- is designed as a later addition to the in-person ask above, for members who don't leave a review on the spot.
See itn/a -- not yet built. - n/aDisplay & reuseWebsite
Reviews are designed to eventually be shown in-academy and on the website
UnverifiedLater phases of this flow call for showing reviews physically in both academies and pulling them onto swingfitacademies.com as proof for prospective members.
See itn/a -- later phase.
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Are we above the review baseline? | Google Business Profile review counts, both sites, compared to the frozen 330 baseline | Combined count trending toward 350 by the target date |
| Who replies to a new review? | Google Business Profile > Reviews tab | A reply from Max within 48 hours, Founder Voice on anything below 4 stars |
| Is there an automated review-request email or WhatsApp message? | CRM Setup > Automation > Workflow Rules / WhatsApp Notifications | There isn't one today -- the ask is an in-person QR code and script, by design |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| The QR-code ask | Remove the physical posters from the bay/desk | No more in-person prompt to leave a review |
Good to know
The ask is deliberately not automated
Google's review policies prohibit incentivized reviews and sentiment-based gating, and reward-for-review mechanics used elsewhere aren't importable as-is. The in-person, unconditional ask is the intended mechanic, not a stand-in for a system that hasn't been built yet.
DIFC is the growth surface to watch
Studio City's rating and volume are already strong (5.0 stars, 277 reviews); DIFC (4.8 stars, 53 reviews) is where new review velocity is expected to show up first.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (4)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
QR review-link posters | other | Active | n/a (static asset) n/a | Links directly to each site's own Google review form; decode-verified 2026-08-13. | Physical posters, bay/desk at Studio City and DIFC state/workstreams/review-flywheel/ (review-ask-poster.html) |
Coach ask script | other | Active | Staff judgment at a satisfying moment n/a | A fixed one-line verbal script pointing the member at the QR code. | state/workstreams/review-flywheel/review-flywheel-map.html state/workstreams/review-flywheel/review-flywheel-map.html |
Review response SOP | other | Active | A new review appears on Google Business Profile n/a | Documents who replies (Max), the 48h window, and Founder Voice tone for negative/mixed reviews. No system enforces the window. | state/workstreams/review-flywheel/review-response-standard.md state/workstreams/review-flywheel/review-response-standard.md |
sfaNPS | function | Inactive/orphan | Designed around an NPS score of 9-10 n/a | Would be the automated trigger for asking a promoter for a review, per the original Hormozi-KB mechanic this flow adapts. Currently an orphan in monitor mode with no live trigger and no score-capture path. | CRM Setup > Developer Hub > Functions references/function-registry.md (sfaNPS entry) |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Lesson_Reports | Google_Review_Status | Field added to the Lesson_Reports spec to track review-readiness at the coach/session level, part of a related post-session capture mechanism, not this flow's own build | Post-session capture (Member Success, phone/WhatsApp check-in) -- not yet in real use |
| Lesson_Reports | NPS_Score | Per-session NPS capture field, feeds the same post-session capture mechanism as Google_Review_Status | Post-session capture (Member Success) |
IDs and references
| What | Value |
|---|---|
| Studio City review link | https://g.page/r/CcYpIwSR2RP2EBM/review |
| DIFC review link | https://g.page/r/CanFBWuAQOi_EBM/review |
| Frozen baseline (2026-08-13) | Studio City 5.0 stars/277, DIFC 4.8 stars/53, combined 330; target >=350 by 2026-10-15 |
All flows › Who got an email
How to check who received an email
Where the proof of an email lives depends on what sent it: automated and one-to-one emails show under Emails on the CRM record, broadcasts show under Campaigns, and billing, store and event emails stay in their own systems.
- Starts when
- Someone asks 'did this person get the email?', or you need to check a send worked.
- Covers
- Every customer-facing email SwingFIT sends, grouped by where you can see that it went out and whether it was opened.
- Systems
- Zoho CRM, Zoho Marketing Automation, Zoho Billing, Zoho Books, Zoho Commerce, Zoho Backstage, WhatsApp
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- Step 1Work out what sent itZoho CRM
First decide: was it an automated or personal email, or a broadcast?
Verified liveSwingFIT sends email from two main places, split on purpose. Zoho CRM sends every email that has to arrive: welcomes, booking and event confirmations, reminders, renewals, follow-ups, win-backs, and anything a staff member sends by hand from a record. Zoho Marketing Automation sends broadcasts: newsletters, promotions, event announcements and other campaign sends to a list or segment. Billing, store and event-ticket emails come from their own systems (step 4).
See itIf you're not sure, open the flow for that email in this handbook. Each email lists what sends it. - Step 2Automated or one-to-one emailZoho CRM
CRM emails show under 'Emails' on the Contact or Lead
Verified liveOpen the person's Contact (or Lead) in Zoho CRM and scroll to the Emails related list. Every email CRM sent them is there with the subject, the time, who it was sent as, and whether it was opened (first and last open). The Source column tells you how it was sent: workflow means an automation sent it, individual means a staff member sent it by hand.
- If it isn't in the list, it didn't goVerified live
An automated email only counts as sent when it appears here. A 'sent' tick or stage field on the record is not proof on its own.
See itCRM → Contacts (or Leads) → the person → Emails related list. - Step 3Broadcast or newsletterZoho Marketing Automation
Campaign emails show under 'Campaigns', not under Emails
Verified liveNewsletters, promotions and other broadcasts sent from Zoho Marketing Automation do not appear in the Emails list. On the person's CRM record they show under Campaigns instead. For the full picture (who it went to, opens, clicks, bounces and unsubscribes) open the campaign itself in Zoho Marketing Automation and check its report.
See itCRM → the person → Campaigns related list. Zoho Marketing Automation → Campaigns → the campaign → Reports / Recipients. - Step 4Billing, store, eventsZoho Billing
Invoices, receipts, store orders and event tickets are checked in their own system
Verified liveThese emails are sent by the system that handles the money or the booking, so they don't appear in CRM at all. Zoho Billing: subscription and renewal emails, receipts, card-expiry notices (Subscription → Email History). Zoho Books: invoice emails (Invoice → History). Zoho Commerce: online store order confirmations (Orders → the order). Zoho Backstage: event ticket confirmations (the event → Attendees). WhatsApp messages show under Messages on the CRM record, not Emails.
See itSee the location for each system above.
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did a new member get their welcome email? | CRM → Contact → Emails | 'You're in…' (or 'Good to have you back…') listed as sent, Source = workflow, ideally with an open |
| Did someone get a booking or event confirmation? | CRM → Contact → Emails | The confirmation listed with the booking date |
| Did a member get this month's newsletter or a promotion? | CRM → Contact → Campaigns, or Zoho Marketing Automation → the campaign → Recipients | The campaign listed for them, with opened/clicked status in the campaign report |
| Did a member get their invoice or receipt? | Zoho Billing → Subscription → Email History; Zoho Books → Invoice → History | The invoice or receipt email logged against their subscription or invoice |
| Did a store buyer get their order confirmation? | Zoho Commerce → Orders → the order | Order confirmation sent |
| Did a staff member email a customer by hand? | CRM → Contact → Emails | Listed with Source = individual and the staff member's name |
Good to know
The split is deliberate
Emails that must arrive (triggered by a booking, payment, credit or membership change) run from CRM. Broadcasts where a missed send is forgiving run from Zoho Marketing Automation, which also handles marketing unsubscribes.
Opens are tracked in both places, separately
CRM tracks opens for its own emails on the Emails list. Marketing Automation tracks opens and clicks for campaigns in its own reports. One doesn't show the other's.
Which inbox replies land in
Automated CRM emails send as info@swingfitacademies.com, so a customer's reply goes to the info@ inbox, not into CRM.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Contacts/Leads → Emails related list | Source | workflow = sent by an automation (workflow rule, schedule or function); individual = sent by a staff member from the record | Zoho CRM |
| Contacts/Leads → Emails related list | status (opened: first_open, last_open, count) | Open tracking for CRM-sent email | Zoho CRM |
| Contacts/Leads → Campaigns related list | Campaign, Member Status | Campaign sends from Zoho Marketing Automation / Zoho Campaigns | ZMA ↔ CRM integration |
IDs and references
| What | Value |
|---|---|
| Channel decision doc | crm_email_templates/flows_bookings/SFA-Booking-Email-ENGINE-REFERENCE.md §1 |
| CRM vs ZMA placement plan | automation/Automation_Placement_Plan_CRM_vs_ZMA.md |
All flows › Facility issues and feedback
When staff report a facility issue, a member shares feedback, or someone can't find something
Two separate Zoho Desk queues: staff log bay, equipment and facility problems; members send ideas, compliments and complaints from the website. Both alert Max, Vic and Akash. A third, separate form logs every 'where is X / how do I' question the team portal didn't answer.
- Starts when
- A staff member reports a facility problem (bay or simulator fault, equipment, leak, lights, anything physical at either location), or a member fills in the 'Share Your Feedback' form on swingfitacademies.com/contact. Or a team member asks someone where something is, or can't find an answer on the team portal.
- Covers
- The two Zoho Desk departments built in July 2026: Facility Issues (internal, staff-reported) and Membership Feedback (member-facing, from the website Contact page). Not the older default 'SwingFIT Academies' or 'SFA Marketing' Desk departments. Also the 'Where is X Log' Zoho Form (built 1 Oct 2026), linked from every team portal hub.
- Systems
- Zoho Desk, Website, Zoho CRM, Zoho Forms
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0Facility issue reportedZoho Desk
A staff member logs the issue as a ticket in the Facility Issues queue
Verified liveStaff report through the 'Report an Issue' form in the Zoho Desk help centre, or straight into the queue from the Facility Issue Report tab in Zoho CRM. Suggested fields: issue type in Category (Bay/Sim, Equipment, Facility/Leak, Other), location in Sub-category (Studio City or DIFC), and a priority (High, Medium, Low). The reporter's name goes in the description. This form is internal only and is not on the public website.
See itZoho Desk → department switcher → Facility Issues → All tickets. Or Zoho CRM → Facility Issue Report tab. - T+0Member feedback sentWebsite
A member submits the 'Share Your Feedback' form on the Contact page
Verified liveThe form on swingfitacademies.com/contact asks for first name, last name, email, subject and description, with a captcha to stop bots. Submitting it creates a ticket in the Membership Feedback queue in Zoho Desk.
See itswingfitacademies.com/contact → 'Share Your Feedback' card. Zoho Desk → Membership Feedback → All tickets. - T+0Team alertedZoho Desk
Zoho Desk emails Max, Vic and Akash about the new ticket
Verified liveEach department has its own workflow rule ('Notify team - new Facility Issue' and 'Notify team - new Membership Feedback') that runs when a ticket is created and emails the three agents in that department. It runs inside Zoho Desk, so nothing else needs to be switched on.
See itYour inbox (check spam too). Zoho Desk → Setup → Automation → Workflow Rules → the department → Active. - Same dayTriageZoho Desk
Max, Vic or Akash takes ownership and sets the status
UnverifiedThe triage team assigns the ticket to an owner and moves it through the status pipeline: Open → Acknowledged → In Progress → On Hold → Escalated → Closed. Acknowledged, In Progress, On Hold and Escalated all still count as open work. For member feedback, the owner replies to the member from the ticket.
See itZoho Desk → the department → ticket → Status and Owner fields. - When fixedClosedZoho Desk
The ticket is closed once the issue is fixed or the member has an answer
UnverifiedClosing the ticket is the record that the bay, equipment or facility problem was sorted, or that the member got a reply. Anything still open is visible in the queue at a glance.
See itZoho Desk → the department → Closed tickets view. - Any timeQuestion loggedZoho Forms
A 'where is X / how do I' question gets logged in the Where is X Log
UnverifiedTwo ways in. On the team portal, the Tell us what's missing button at the bottom of every hub and the Find anything page opens the form with the page it came from already filled in (hidden Source field). Off the portal, whoever gets asked by WhatsApp, Cliq or in person logs it from the same form link, and Source stays blank, which means "asked a person". The form asks who asked (Coach, Member Success or Management), what they were looking for, and whether it was on the portal.
See itZoho Forms → Where is X Log → Entries.
Emails and messages
TeamNew Facility Issue alertVerified liveZoho Desk default new-ticket alert
TeamNew Membership Feedback alertVerified liveZoho Desk default new-ticket alert
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| What facility problems are open right now? | Zoho Desk → Facility Issues → Open tickets (or the CRM Facility Issue Report tab) | Every open ticket has an owner and a status past Open |
| Did a member's feedback arrive? | Zoho Desk → Membership Feedback → All tickets, search by the member's email | A ticket with their subject and description |
| Is the website form still working? | swingfitacademies.com/contact | The 'Share Your Feedback' card shows the fields and a captcha |
| Are the alerts on? | Zoho Desk → Setup → Workflow Rules, in each department | Both 'Notify team' rules listed as active |
| How many 'where is X' questions reached a person this week? | Zoho Forms → Where is X Log → Entries, filter Source is empty, this week | The count is read every Monday; it should fall after the new portal hubs went live (1 Oct 2026). 'No, it isn't there' rows are the list of answers to add to the portal. |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Team alerts | Zoho Desk → Setup → Workflow Rules → the department's 'Notify team' rule → deactivate | New tickets still land in the queue, but nobody is emailed about them |
| Member feedback form | Zoho Desk → Setup → Web Forms → 'Membership Feedback' → toggle off, and remove the card from the Contact page | Members can no longer send feedback from the website |
| Facility issue intake | Zoho Desk → Setup → Web Forms → 'Facility Issue Report' → toggle off; CRM → hide the Facility Issue Report tab | Staff can no longer log facility problems into the queue |
| Where is X Log | Zoho Forms → Where is X Log → Settings → stop accepting responses, and remove the button from the portal hubs | Questions are no longer logged, so the Monday count stops |
Good to know
Two queues on purpose
Facility problems and member feedback are different audiences with different content, so they are kept in separate departments and never mixed.
Facility reporting stays internal
The Facility Issue form is for staff only and is deliberately not on the public website. Members use the feedback form instead.
The status pipeline is per department
Zoho Desk sets statuses per department, so both departments were given the same six statuses. A change in one does not carry over to the other.
info@ is not a ticket inbox
Emails to info@swingfitacademies.com stay in Gmail. They do not create tickets in these two queues.
Blank Source means a person was asked
Portal buttons always fill in Source (coaches-hub, member-success-hub, management-hub, find-page, home). Only entries typed in by hand leave it blank, so the blank rows are the ones that reached a person.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (8)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Facility Issues1043640000010386029 | department | Active last run 2026-08-31 (late | n/a Help centre name 'Report an Issue'. Agents: Max, Vic, Akash, Richard. | Queue for staff-reported bay, equipment and facility problems. Layout 1043640000010388849. | Zoho Desk (org 866469175) state/facility-issues-tracker-map.html |
Membership Feedback1043640000010402029 | department | Active | n/a Help centre name 'Share Feedback'. Agents: Max, Vic, Akash. | Queue for member ideas, compliments and complaints from the website form. | Zoho Desk (org 866469175) state/membership-feedback-map.html |
Notify team - new Facility Issue | workflow rule | Active | Ticket created none | Alert: built-in 'Notify all agents when a new Ticket is created' → emails the department's agents. | Zoho Desk → Setup → Workflow Rules (Facility Issues) Desk UI only |
Notify team - new Membership Feedback | workflow rule | Active | Ticket created none | Alert: custom 'Notify agents when a new Ticket is created' → emails Max, Vic, Akash. | Zoho Desk → Setup → Workflow Rules (Membership Feedback) Desk UI only |
Facility Issue Report (Advanced Web Form) | web form | Active | Form submit Internal only; not embedded on the website | Fields: First Name, Last Name, Email, Phone, Subject, Description, Priority. Domain + return URL swingfitacademies.com. | Zoho Desk → Setup → Web Forms (Facility Issues) Desk UI only |
Membership Feedback (Advanced Web Form) | web form | Active | Form submit (posts to desk.zoho.com/support/WebToCase) Captcha required (added 2026-07-22) | Fields: First Name, Last Name, Email, Subject, Description, Captcha. Creates a ticket in Membership Feedback. | Zoho Desk → Setup → Web Forms (Membership Feedback); embedded in an Elementor HTML widget on swingfitacademies.com/contact domains/member-success/membership_feedback_embed.html |
Facility Issue Report | CRM web tab | Active | n/a n/a | Opens https://desk.zoho.com/agent/swingfitacademies/facility-issues/tickets/list/all-cases | Zoho CRM navigation (repurposed 'Old Coach Clients' tab) CRM Setup → Web Tabs |
Where is X Log (Zoho Form)WhereisXLog | web form | Active | Form submit Public link; hubs prefill hidden SingleLine1 via ?SingleLine1=<source> | Logs portal misses and questions asked of a person. Signal: weekly count of blank-Source rows (Mondays, Max). | Zoho Forms (portal swingfitacademies1) state/workstreams/system-portal-redesign/where-is-x-form.md |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Desk Tickets (Facility Issues) | category | Issue type: Bay/Sim, Equipment, Facility/Leak, Other (free text) | Reporter / triage |
| Desk Tickets (Facility Issues) | subCategory | Location: Studio City or DIFC (free text) | Reporter / triage |
| Desk Tickets (both) | status | Open → Acknowledged → In Progress → On Hold → Escalated → Closed (first five are status type Open) | Triage owner |
| Zoho Form: Where is X Log | Radio | Who asked? Coach / Member Success / Management (required) | Person logging |
| Zoho Form: Where is X Log | SingleLine | What were they looking for? (required) | Person logging |
| Zoho Form: Where is X Log | Radio1 | Was it on the portal? Yes, they missed it / No, it isn't there / Not sure (required) | Person logging |
| Zoho Form: Where is X Log | SingleLine1 | Source (hidden). coaches-hub · member-success-hub · management-hub · find-page · home; blank = asked a person | Portal link prefill |
IDs and references
| What | Value |
|---|---|
| Desk org | 866469175 (portal swingfitacademies) |
| Facility Issues dept | 1043640000010386029 |
| Membership Feedback dept | 1043640000010402029 |
| Facility queue link | https://desk.zoho.com/agent/swingfitacademies/facility-issues/tickets/list/all-cases |
| info@ From Address (Membership Feedback) | 1043640000010433001 (display sender only, not an inbound channel) |
| Where is X Log public link | https://forms.zohopublic.com/swingfitacademies1/form/WhereisXLog/formperma/c5CEKReWlpjBUUd7Flq_Tzix6izgzFibUxMVyu_fxks |
All flows › Reports and digests
When a scheduled report or digest is due
The team receives reports and digests through a mix of scheduled tasks, CRM schedules and manual data pulls, at daily, weekly and monthly cadences.
- Starts when
- A Cowork/cloud scheduled task (cron) fires, or a CRM Schedule fires a Deluge function, or a real analyst/session manually builds a spreadsheet on request.
- Covers
- Every recurring report/digest the team receives (business snapshot, scorecard, alignment review, rebooking digest, coach digests, guest report) plus the manually-produced AR/unpaid spreadsheets and CRM Home dashboards. Does not cover one-off ad hoc data pulls outside these named reports.
- Systems
- Zoho CRM, Zoho Billing, Zoho Books, Zoho Analytics, Zoho Backstage, Cliq, Zoho Flow
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- weekly, Mon 09:00 Asia/Dubai (cron 0 5 * * 1 UTC)Mon 09:00Zoho CRM
Monday business snapshot task fires
UnverifiedA Cowork scheduled task named
SwingFIT Monday snapshot (members · MRR · joins/cancels · aged dunning)fires weekly and is designed to writeautomation/monday-snapshot.mdwith the week's core numbers, replacing the retired daily health scan.See itScheduled tasks list (trig_01FN7ETCReJcft7ZwefHeXtP) shows next/last run; the target file isautomation/monday-snapshot.mdin the AI OS folder. - weekly, ad hocWeeklyZoho CRM
Weekly scorecard reviewed
UnverifiedA five-metric scorecard (Booked Evaluations, Eval→Member Conversion, MRR, At-Risk Member Flags, Max-Hours-in-Ops) lives as a Cowork artifact plus a static HTML copy. It is built from live CRM COQL, Zoho Billing and the DRIP audit, and is designed to feed the
2+ weeks off-trackitems into the Monthly Alignment Review.See itstate/workstreams/weekly-scorecard/swingfit-weekly-scorecard-v2-2026-08-19.html; the Cowork artifact of the same name. - weekly, Mon 08:00 Asia/Dubai (cron 0 8 * * 1 Asia/Dubai)Mon 08:00Zoho CRM
Alignment review task fires
Verified liveA Cowork scheduled task named
Swingfit monthly alignment reviewruns and computes coach-hours and bay-hours live via COQL against the Bookings and Coaches modules (non-cancelled bookings, matched by Resource_Name, divided by the current coach/bay capacity), readingstate/workstreams/monthly-alignment-review/live-inputs.mdfor any manually logged exceptions (bay outages, coach leave, roster/bay-count changes in flight).See itScheduled tasks list (trig_01T3myi1gFkJ56pie1eBEjg8);state/workstreams/monthly-alignment-review/. - daily (schedule says Daily; older docs claim twice-daily 3:30pm/10:30pm)Daily ~15:30 DubaiZoho CRM
Rebooking digest sent
Verified livesfabookingsweep(internal namesfaRebookingDigest, CRM Schedulerebookingsweepsfa330pm) finds today's coaching bookings that ended 30+ minutes ago with no future lesson or practice booking on file, groups them by location and category into one HTML email, and sends it viasendmailfrom info@swingfitacademies.com to max@ and akash@ only.See itEmails sent from info@swingfitacademies.com with subject referencing rebooking; CRM Schedules list. - daily 07:30 Asia/Dubai07:30 dailyZoho CRM
Coach morning digest posted
Verified livesfaCoachMorningDigest(CRM Schedule, Daily) posts each coach's day — including that day's lesson-report form links — to the coach's own chat via thecoachdigestbotCliq bot, using a hardcoded per-function roster of coach name/resources/email. It also collects any coach whose Cliq post returned no reachable user and emails a summary to max@.See itCoach's Cliq chat with coachdigestbot; CRM Schedules list (sfaCoachMorningDigest). - daily ~20:00 Asia/Dubai~20:00 dailyZoho CRM
Coach end-of-day nudge posted
From codesfaCoachEODNudge(CRM Schedule, Daily) runs the same per-coach Cliq-bot post pattern as the morning digest, using its own separate hardcoded coach roster, as an evening reminder rather than a morning one.See itCoach's Cliq chat with coachdigestbot; CRM Schedules list (sfaCoachEODNudge). - daily 08:00 Asia/Dubai08:00 dailyZoho CRM
Daily guest report sent
Verified livesfaDailyGuestReport(CRM Schedule, Daily, entity id 1446733000000762001) pulls the day's Backstage/guest activity and emails a report; a coach-notify feature was added and the schedule was flipped from testMode to fully live on 2026-09-06.See itCRM Schedules list (sfaDailyGuestReport); the recipient inbox. - whenever a no-show is flaggedon no-showZoho CRM
No-show alert posted to Cliq
Verified livesfanoshowalertfires once per booking whenNoshow_Flag= 'No-show', posting a one-line alert ('No-show: <member> - <resource>, <date/time>') to the matching coach's own Cliq chat (via a hardcoded coach-name → Cliq-chat-ID map) and to a fixed Member Services Cliq chat.See itCoach's Cliq chat; the Member Services Cliq chat. - pulled by staff, no fixed cadenceOn demandZoho CRM
Zoho Analytics dashboards checked
UnverifiedThe SFA Leadership and SFA Combined Zoho Analytics workspaces (e.g. the Lead Quality & Pipeline / Funnel Dashboard) hold live dashboards staff open themselves. Nothing here pushes a digest out; the scorecard reads some of the same underlying numbers.
See itZoho Analytics, SFA Leadership / SFA Combined workspaces. - produced when Akash or Max asks, no fixed cadenceOn requestZoho Books
AR / unpaid spreadsheets produced for Akash
From codeSpreadsheets such as
Live_Unpaid_By_Salesperson.xlsx, theSwingFIT_AR_*set (Action Dashboard, ToAction, Removed, by Type) andSwingFIT_Membership_Still_Open/SwingFIT_PAYG_Unregistered_Payments/SwingFIT_Paused_Membershipsare built by a Claude/Cowork session pulling live Zoho Books and CRM data on request and saved to the AI OS root, not generated by any recurring scheduled task.See itAI OS folder root; file dates in the filename itself. - built once, viewed continuouslyStanding pageZoho CRM
CRM Home calendars/dashboards available
UnverifiedThe CRM Home Calendars (CHC) workstream built calendar/dashboard views directly on the CRM Home page for staff to check themselves — a standing page, not a pushed digest.
See itZoho CRM Home page (per-user layout).
Emails and messages
TeamRebooking digestVerified liveRebooking digest (grouped by location)
Full text ($HOME/arch/crm_deluge_source/sfabookingsweep.deluge)
TeamCoach morning digestVerified liven/a (Cliq message, not email)
TeamCoach EOD nudgeUnverifiedn/a (Cliq message)
TeamDaily guest reportVerified liveDaily guest report
TeamNo-show alertVerified liven/a
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Where's this week's business snapshot? | automation/monday-snapshot.md in the AI OS folder | a dated file with member/MRR/joins-cancels/dunning numbers less than a week old |
| What's our current scorecard? | the Weekly Scorecard Cowork artifact / state/workstreams/weekly-scorecard/ | a dated build with all five metric cards populated |
| Did the rebooking digest go out today? | info@swingfitacademies.com Sent Mail | a same-day email to max@ and akash@ |
| Did a coach get their morning digest? | the coach's Cliq chat with coachdigestbot | a same-morning message with that day's lessons and form links |
| Where do the AR/unpaid numbers for Akash come from? | the dated SwingFIT_AR_*/Live_Unpaid_* files at the AI OS root | a file dated within the current cycle, matching Zoho Books |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Monday business snapshot | Scheduled tasks (trig_01FN7ETCReJcft7ZwefHeXtP) | the weekly business-numbers task stops firing |
| Rebooking digest | CRM Schedule rebookingsweepsfa330pm / the sfabookingsweep function | max@/akash@ stop receiving the daily rebooking email |
| Coach morning digest | CRM Schedule sfaCoachMorningDigest | coaches stop getting their 07:30 Cliq message |
| Alignment review | Scheduled tasks (trig_01T3myi1gFkJ56pie1eBEjg8) | the weekly-firing review task stops |
Good to know
The scorecard reads several other systems' numbers
Its five cards pull from CRM COQL, Zoho Billing (both orgs) and the DRIP time-use audit rather than holding any numbers of its own.
Alignment review computes capacity live
Coach-hours and bay-hours are recomputed from Bookings each run rather than typed in; only genuine exceptions (a bay out of service, a coach on leave) are logged by hand in live-inputs.md.
Rebooking digest recipients are a deliberate, confirmed list
Max confirmed max@ and akash@ are the intended recipients for this internal staff digest — it is not member-facing.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (7)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
SwingFIT Monday snapshottrig_01FN7ETCReJcft7ZwefHeXtP | schedule | Active last run 2026-09-21T05:11 | cron 0 5 * * 1 (UTC) = Mon 09:00 Asia/Dubai none — unconditional weekly fire | Intended to pull member/MRR/joins-cancels/aged-dunning numbers and write automation/monday-snapshot.md. | Cowork scheduled tasks n/a — no target file has ever been produced |
Swingfit monthly alignment reviewtrig_01T3myi1gFkJ56pie1eBEjg8 | schedule | Active last run 2026-09-21T04:07 | cron 0 8 * * 1 Asia/Dubai (fires every Monday) none | Computes coach-hours and bay-hours live via COQL against Bookings + Coaches, reads live-inputs.md for manual exceptions. | Cowork scheduled tasks state/workstreams/monthly-alignment-review/live-inputs.md |
sfabookingsweep (internal: sfaRebookingDigest) | function | Active | Daily schedule Coaching bookings (Resource_Name starts with 'Coach', excludes Evaluation/Cancelled) ended >30 min ago with no future lesson/practice booking. | Builds an HTML digest grouped by location/category and emails it via crm_info connection to max@ and akash@ only; stamps Rebook_Lesson_Booked/Rebook_Practice_Booked/Stamped_Coach on the booking. | Zoho CRM Schedule 'rebookingsweepsfa330pm' crm_functions_live/functions/sfabookingsweep.deluge |
sfaCoachMorningDigest | function | Active | Daily 07:30 Asia/Dubai per-coach hardcoded roster (c1 Richard, c2 Stian, c3 Harry, c4 Pradeep, c6 Henry) | Posts each coach's day plus lesson-report form links to coachdigestbot; emails max@ a summary of any coach the bot could not reach. | Zoho CRM Schedule 'sfaCoachMorningDigest' $HOME/arch/crm_deluge_source/sfacoachmorningdigest.deluge |
sfaCoachEODNudge | function | Active | Daily ~20:00 Asia/Dubai separate per-coach hardcoded roster (c1 Richard, c2 Stian, c3 Harry, c4 Pradeep, c6 Henry) | Same Cliq-bot post pattern as the morning digest, run in the evening. | Zoho CRM Schedule 'sfaCoachEODNudge' $HOME/arch/crm_deluge_source/sfacoacheodnudge.deluge |
sfaDailyGuestReport1446733000000762001 (api_name sfadailyguestreport) | function | Active | Daily 08:00 Asia/Dubai none stated beyond daily fire | Builds and emails the day's guest/Backstage report; coach-notify feature added and testMode flipped to live 2026-09-06. | Zoho CRM Schedule 'sfaDailyGuestReport' references/function-registry.md line 275 |
sfanoshowalert | workflow rule | Active | Noshow_Flag = 'No-show' fires once (Noshow_Alert_Sent guard) | Posts a one-line Cliq alert to the coach's own chat (via hardcoded coachChatMap of 5 names → Cliq chat IDs) and to a fixed Member Services Cliq chat. | CRM Workflow 'NOSHOW Internal Alert' (field update on Bookings) $HOME/arch/crm_deluge_source/sfanoshowalert.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Bookings | Rebook_Lesson_Booked | whether the client already has a future lesson booked | sfabookingsweep |
| Bookings | Rebook_Practice_Booked | whether the client has used practice access since the lesson | sfabookingsweep |
| Bookings | Stamped_Coach | the coach name parsed off Resource_Name for this booking | sfabookingsweep, sfanoshowalert |
| Bookings | Noshow_Alert_Sent | guard so the internal no-show Cliq alert fires once per booking | sfanoshowalert |
IDs and references
| What | Value |
|---|---|
| Monday snapshot scheduled task | trig_01FN7ETCReJcft7ZwefHeXtP |
| Monthly alignment review scheduled task | trig_01T3myi1gFkJ56pie1eBEjg8 |
| Daily Guest Report CRM entity id | 1446733000000762001 |
| sfabookingsweep coach owner id map (Richard) | 6296422000000479001 |
All flows › Recruitment
When we hire a coach or staff member
Hiring runs through Zoho Recruit's pipeline and a daily follow-up task, with coach setup completed by hand across GolfManager, Cliq and several CRM automations.
- Starts when
- A Job Opening is posted in Zoho Recruit and candidates start applying, or Max/Akash decide to open a new role.
- Covers
- The recruiting/hiring pipeline from job opening to a new coach or staff member's first day, plus what has to change elsewhere in the CRM automations when a coach joins or leaves. Does not cover ongoing performance management or disciplinary process.
- Systems
- Zoho Recruit, Zoho CRM, GolfManager, Cliq, Zoho People
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- ongoingSourcingZoho Recruit
Job opening posted and candidates tracked
Verified liveJob Openings (currently 3: Member Success Executive, PGA Golf Coach x2, Junior PGA Golf Coach — all 'In-progress') hold candidates who move through Candidate_Status stages (New → Attempted to Contact → Contacted → Reviewed → Contact in Future / Rejected). 57 candidates are currently in the pipeline across the three openings.
See itZoho Recruit, Job Openings module and each opening's Candidates tab. - weekday 07:30 Asia/Dubai (currently disabled)07:30 weekdaysZoho Recruit
Recruiting Desk sweep
UnverifiedA scheduled task ('Swingfit recruiting desk weekday 0730 2') is designed to sweep the Recruit pipeline each weekday morning, draft Gmail follow-ups for candidates waiting on a reply, and flag any candidate who needs Max to name an interview time or give a verdict.
See itScheduled tasks list (trig_015VuA4RkrTZPbXw2RgmHTpy); Gmail drafts folder. - per candidateInterview stageZoho Recruit
Interview scheduled and evaluated
From codeInterviews are booked in Zoho Recruit and evaluated against the HR Master interview kit: the Competency-Based Interview Question Bank, two Interviewer Guides, the Interview Feedback Form, and the Invitation to Interview letter.
See it"HR Master (SwingFIT)/07 Recruitment/"; Zoho Recruit candidate timeline. - per hireOfferZoho Recruit
Offer generated
UnverifiedZoho Recruit can generate and send an offer against a candidate record (change candidate/offer status). Contract paperwork itself lives in the HR Master document set, not in Recruit.
See itZoho Recruit candidate record, Offer tab; "HR Master (SwingFIT)/01 Employment Contracts & Amendments/". - day oneOnboardingZoho CRM
Employment paperwork and onboarding pack signed
From codeThe New Joiner Checklist, the Employment Contract, the coach or admin Onboarding Letter, and the Employee Handbook + Policy Acknowledgment (all in the HR Master 02 Onboarding folder) are the documents a new hire signs day one; the README recommends attaching them to a Zoho People onboarding flow's Documents & Policies step.
See it"HR Master (SwingFIT)/02 Onboarding/". - day one / first working dayResource setupGolfManager
Coach set up as a bookable resource
UnverifiedA new coach needs a GolfManager coach/resource record before members can book lessons with them, and a matching Resource_Name pattern (e.g. 'Member Coach <Name> (SC)') that the CRM automations key off of.
See itGolfManager tenant records; CRM Bookings Resource_Name picklist. - day oneAutomation rostersZoho CRM
Coach added to every hardcoded automation roster
From codeAt least four separate Deluge functions carry their own hand-maintained coach roster rather than reading one shared list:
sfabookingsweep's coachMap (name → CRM owner id, used for rebooking tasks),sfanoshowalert's coachChatMap (name → Cliq chat id, used for no-show alerts), andsfaCoachMorningDigest/sfaCoachEODNudge's c1-c6 maps (name, bookable resources, email, used for the daily Cliq digests). Each must be edited by hand when a coach joins or leaves.See it$HOME/arch/crm_deluge_source/sfabookingsweep.deluge, sfanoshowalert.deluge, sfacoachmorningdigest.deluge, sfacoacheodnudge.deluge.
Emails and messages
CustomerInvitation to InterviewUnverifiedInterview invitation
CustomerOnboarding Letter (Coach / Admin)UnverifiedWelcome / onboarding letter
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| How many open roles do we have? | Zoho Recruit, Job Openings module | 3 openings currently 'In-progress': Member Success Executive, PGA Golf Coach (x2 positions), Junior PGA Golf Coach |
| Is the Recruiting Desk still running? | Scheduled tasks list, trig_015VuA4RkrTZPbXw2RgmHTpy | enabled = true and last_run = SUCCEEDED |
| What do I hand a new coach on day one? | "HR Master (SwingFIT)/02 Onboarding/" | contract, onboarding letter, New Joiner Checklist, Employee Handbook + Acknowledgment |
| What breaks if we forget to add a new coach everywhere? | sfabookingsweep.deluge, sfanoshowalert.deluge, sfacoachmorningdigest.deluge, sfacoacheodnudge.deluge coach maps | the new coach's name appears in all four maps with matching Resource_Name strings |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| Recruiting Desk sweep | Scheduled tasks (trig_015VuA4RkrTZPbXw2RgmHTpy) | the daily candidate-sweep and draft-follow-up task stops firing |
Good to know
HR Master is Studio City only
The HR document library deliberately excludes DIFC-specific paperwork — all staff are employed under the Studio City FZ LLC, governed by UAE Federal Decree-Law No. 33 of 2021.
Recruiting Desk was built around a specific gap
It was built 2026-08-11 after a sweep found candidates sitting for up to 12 days with no action, all waiting on a decision only Max could make — the task drafts the follow-up so Max only has to approve or pick a time.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (4)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
Swingfit recruiting desk weekday 0730 2trig_015VuA4RkrTZPbXw2RgmHTpy | schedule | Inactive last run 2026-09-23T03:41 | cron CRON_TZ=Asia/Dubai 30 7 * * 1-5 none stated | Sweeps the Zoho Recruit pipeline, drafts Gmail follow-ups for stalled candidates, flags items needing Max's decision. | Cowork scheduled tasks n/a |
sfabookingsweep coach map | function | Active | n/a (lookup table inside the digest function) coach name parsed from Resource_Name | Maps coach first name to a CRM owner id for task assignment; currently 8 entries including a departed coach. | $HOME/arch/crm_deluge_source/sfabookingsweep.deluge $HOME/arch/crm_deluge_source/sfabookingsweep.deluge lines 39-46 |
sfanoshowalert coach map | function | Active | n/a (lookup table inside the alert function) coach name parsed from Resource_Name | Maps coach first name to a Cliq chat id for the no-show alert; currently 5 entries, missing the newest coach. | $HOME/arch/crm_deluge_source/sfanoshowalert.deluge $HOME/arch/crm_deluge_source/sfanoshowalert.deluge lines 38-43 |
sfaCoachMorningDigest / sfaCoachEODNudge coach maps | function | Active | n/a (lookup table inside each digest function) each coach entry lists name, bookable resources, email | Drives which coaches get the daily Cliq digest/nudge and which bookings map to them; 5 coaches each, kept in sync with each other but not with the other two functions above. | $HOME/arch/crm_deluge_source/sfacoachmorningdigest.deluge, sfacoacheodnudge.deluge sfacoachmorningdigest.deluge / sfacoacheodnudge.deluge, lines 8-31 |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Job_Openings (Recruit) | Job_Opening_Status | whether a role is open/in-progress/closed | manual, Zoho Recruit UI |
| Candidates (Recruit) | Candidate_Status | pipeline stage (New/Contacted/Reviewed/etc.) | manual + Recruiting Desk drafts |
Full email text
Invitation to Interviewnot found
IDs and references
| What | Value |
|---|---|
| Recruiting Desk scheduled task | trig_015VuA4RkrTZPbXw2RgmHTpy |
| Job Opening — Member Success Executive | 819727000001058058 |
| Job Opening — PGA Golf Coach | 819727000000904019 |
| Job Opening — Junior PGA Golf Coach | 819727000000904003 |
All flows › Cliq alerts
Which team alerts go to Cliq, and who sees them
An inventory of every automation that posts into Zoho Cliq, which channel or DM it lands in, and whether it is actually reaching the people it is meant to reach.
- Starts when
- Many different triggers - a POS/Commerce sale, a GolfManager booking, a Bookings record edit, a daily/hourly schedule, a Zoho Form submission, a Zoho Creator record. Each is listed under its own step below.
- Covers
- Covers every CRM workflow rule, CRM schedule, and Zoho Flow function found in the archive that calls the Cliq API (invokeurl to cliq.zoho.com, or zoho.cliq.postToChannel/postToBot). Does not cover Cliq's own built-in mentions/notifications, or the human conversation inside these channels.
- Systems
- Zoho CRM, Zoho Flow, Zoho POS/Commerce, GolfManager, Zoho Checkout, Zoho Billing, Zoho Forms, Zoho Creator, Cliq, WhatsApp
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- T+0 (real time)POS/Commerce saleCliq
Every POS/Commerce sale over 250 AED posts to #PAYG Sales
Verified liveSalePOS_Cliq_Notification(Zoho Flow, folder 'Zoho POS/Commerce Flows') fires on a POS or Commerce invoice, checks the rate, and for anything over 250 AED posts service, amount, customer email/name, salesperson and location to the #PAYG Sales channel viazoho.cliq.postToChannel("paygsales", ...).See itCliq > #PAYG Sales channel - T+0 (real time)New evaluation/intro bookingCliq
A confirmed or failed evaluation/intro-to-golf booking posts to #New Bookings
Verified liveCRM_UpdatePayStatus_GMBookingCreationandZCRM_UpdatePaymentStatus_GMBookingCreation(two near-duplicate Flow functions, Zoho Checkout - Zoho CRM folder) post 'FYI, New Booking:' with the appointment time, customer and coach to the same channel (zoho.cliq.postToChannel("zohobookingsm", ...)) on a successful Golf Swing Evaluation / Intro to Golf payment.Zcliq_PaymentFailed_Golf_Swing_EvaluationandZcliqMsg_PaymentFailed_intro_to_golf_post the same style of message, headed 'FYI, New Booking, Payment Failed:', into the identical channel when the payment fails.See itCliq > #New Bookings channel - T+0 (on Noshow_Flag edit)No-show alertCliq
A no-show alert is designed to reach the coach's own chat plus a Member Success chat
From codesfanoshowalert(CRM workflow rule 'NOSHOW Internal Alert' on Bookings) posts 'No-show: member - resource, date/time.' to a coach's personal 1:1 Cliq chat (matched by first name against a hardcoded map) and to one fixed Member Success chat. Covered in full, including its current on/off status, in the separate no-show flow.See itSee the 'When someone doesn't show up' flow for the live status of this rule - daily 10:00Coach pre-session briefingCliq
Each morning, coaches with an evaluation booked that day are meant to get a 'BEFORE YOU WALK IN' DM
Verified liveThe 'Coach Pre-Session Briefing Sweep' schedule (Evaluation_Booking, 10:00 daily) calls
sfaEvalBriefingSendTest, which resolves the coach from the booking and posts a player name, session time, intake status and a Game Plan Builder link straight to that coach's personal Cliq chat, using the same hardcoded coach-name-to-chat-ID map as the no-show alert.See itZoho CRM setup > Automation > Schedules > 'Coach Pre-Session Briefing Sweep'; the coach's own Cliq chat - T+0 (on session end)Coach post-session debriefCliq
Right after a session ends, the coach is meant to get a debrief-form DM
Verified liveThe 'Coach Post-Session Debrief Send' workflow rule (Evaluation_Booking, date-based on End_Date_and_Time) calls
sfaEvalDebriefSend, which posts an 'EVAL DEBRIEF' message with a prefilled Eval Debrief form link to the same coach's personal Cliq chat, using the identical chat-ID map as the briefing sweep.See itZoho CRM setup > Automation > Workflow Rules > Evaluation_Booking > 'Coach Post-Session Debrief Send'; the coach's own Cliq chat - daily 09:00Dunning case listCliq
Past-due and unpaid membership cases are grouped by salesperson and DMed once a day
UnverifiedsfaDunningTeamAlert(schedule, daily 09:00) pulls Zoho Billing subscriptions in PAST_DUE/UNPAID across both orgs, buckets each case under the salesperson on record (using a hardcoded name-to-email map), and sends a per-person case list as a Cliq bot DM addressed by resolved Cliq user id, chunking long lists. Any salesperson it can't map, or any other warning, goes to Max as a separate alert.See itZoho CRM setup > Automation > Schedules > 'sfaDunningTeamAlert'; each salesperson's Cliq DMs from the bot - T+0 (on form submit)Form announcementCliq
A Zoho Forms submission posts a member-facing style announcement to #Announcements
From codeZForms_ZCliqAnnouncement(Flow, folder 'Zoho Forms - Zoho Cliq', flow 'ZForms - ZCliq/Announcements') takes the submitted coach, player email and evaluation-conversion outcome and posts it straight to the #Announcements channel.See itCliq > #Announcements channel - T+0 (on record created)Pause request notificationCliq
A new pause request in Zoho Creator is designed to post a Cliq channel message
UnverifiedTwo Zoho Flows in the 'Zoho Creator Pause' folder - 'Cliq Notification' and 'Cliq Notification Cancel' - trigger on a new Zoho Creator record and use Cliq's built-in 'Message in channel' action to post it. Which channel they target is set inside that native Flow action, not visible in the captured configuration.
See itZoho Flow > 'Zoho Creator Pause' folder > 'Cliq Notification' / 'Cliq Notification Cancel' - T+0 (on subscription purchase)Practice pass notificationCliq
A new Practice Passes purchase posts to #Practice Passes
From codePracticePassesCliqNotification(Flow function) posts the product/plan name, customer email/name and location to the #Practice Passes channel viazoho.cliq.postToChannel("practicepasses", ...).See itCliq > #Practice Passes channel - T+0 (inbound message)WhatsApp inbound notificationCliq
An inbound WhatsApp message is designed to post into #Inbound WhatsApp
UnverifiedInbound WhatsApp messages post as 'New WhatsApp message / From: ... / Message: ... / Conversation: ...' into the #Inbound WhatsApp channel, from either the connected personal account or a 'Comms Bot' identity. A related hourly sweep,
sfaWhatsAppStaleSweep, checks for conversations left unresolved 10+ minutes and posts a nudge into the same channel viabot_unique_name=commsbot.See itCliq > #Inbound WhatsApp channel - daily 08:00Daily guest/member event reportCliq
A daily digest of the day's group-class signups posts to #Event Updates
Verified livesfaDailyGuestReport(schedule, daily 08:00) emails a member/guest signup digest and also posts the same digest to the #Event Updates channel via Membership Bot, usingzoho.cliq.channelsbynamewith the channel's internal name 'eventupdates'.See itCliq > #Event Updates channel - daily 07:30 / daily 20:00 / on booking createCoach digest bot messagesCliq
A coach morning digest, an end-of-day nudge, and a same-day booking ping are all designed to DM the coach directly
UnverifiedsfaCoachMorningDigest(daily 07:30) andsfaCoachEODNudge(daily 20:00) are meant to DM each coach their day's sessions and any missing lesson reports;sfaSameDayBookingPing(on Bookings create, after 07:30) is meant to DM a coach the moment a same-day booking lands on their diary. All three go through Coach Digest Bot'spostToBotwith the coach's email as theuseridstarget.See itCoach's own chat with Coach Digest Bot - hourlyMember Success roadmap-gap digestCliq
An hourly sweep is designed to post a call list of evaluations due within 24h to #Member Success - Roadmap Gaps
UnverifiedsfaEvalIntakeBackstop(schedule, hourly) is designed to post a 'Member Success call list' line per evaluation added and due within 24 hours to the #Member Success - Roadmap Gaps channel.See itCliq > #Member Success - Roadmap Gaps channel - T+0 (on lesson report / round log submit)Player level-up notificationCliq
When a player's score advances them a level, their coach gets a Cliq ping
From codesfaCreateLessonReport(called from the Lesson Report form/app) andsfaLogRound(Flow function) both carry a 'level-up' branch that, when a player's score crosses the threshold for their next roadmap level, posts a Cliq message to a resolved coach chat.See itCoach's own Cliq chat, following a level-up lesson report or logged round
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Did a POS/Commerce sale post to the sales channel? | Cliq > #PAYG Sales | A 'FYI, New Sale From POS/Commerce:' message appears within a minute or two of the sale, for anything over 250 AED |
| Did a new or failed evaluation booking show up? | Cliq > #New Bookings | A 'FYI, New Booking:' or 'FYI, New Booking, Payment Failed:' message appears with the right customer, time and coach |
| Did the coach actually get their morning digest, EOD nudge or same-day ping? | The coach's own Cliq chat with Coach Digest Bot | A message addressed directly to the coach with their real name and session list. |
| Did the daily guest/member report reach #Event Updates? | Cliq > #Event Updates | A 'Daily Guest Report - date' message appears in the channel once a day around 08:00. |
| Did a salesperson get their dunning case list? | That salesperson's Cliq DMs from the bot named 'membershipbot' | A daily message listing their past-due/unpaid cases |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| POS/Commerce sale alert | Zoho Flow > 'Zoho POS/Commerce Flows' > 'SalePOS_Cliq_Notification' | No more #PAYG Sales postings for POS/Commerce sales |
| Evaluation/intro booking + payment-failure alert | Zoho Flow > 'Zoho Checkout - Zoho CRM' folder (the flows calling CRM_UpdatePayStatus_GMBookingCreation / ZCRM_UpdatePaymentStatus_GMBookingCreation / the two payment-failed functions) | No more #New Bookings postings for evaluation/intro checkout activity |
| Coach pre-session briefing | Zoho CRM setup > Automation > Schedules > 'Coach Pre-Session Briefing Sweep' | Coaches stop getting the 'BEFORE YOU WALK IN' DM ahead of an evaluation |
| Coach post-session debrief prompt | Zoho CRM setup > Automation > Workflow Rules > Evaluation_Booking > 'Coach Post-Session Debrief Send' | Coaches stop getting the 'EVAL DEBRIEF' prompt after a session ends |
| Dunning case list | Zoho CRM setup > Automation > Schedules > 'sfaDunningTeamAlert' | Salespeople stop getting their daily past-due/unpaid case list |
| Form announcement | Zoho Flow > 'Zoho Forms - Zoho Cliq' folder > 'ZForms - ZCliq/Announcements' | No more #Announcements postings from that form |
| Practice pass notification | Wherever PracticePassesCliqNotification is wired (Practice Passes purchase flow) | No more #Practice Passes postings on a new pass purchase |
Good to know
Coach chats are matched by first name, not by ID lookup
The no-show alert, the pre-session briefing and the post-session debrief all resolve a coach's Cliq chat the same way: a hardcoded map of first name to Cliq chat ID (Richard, Stian, Harry, Pradeep, Brad, Henry). All three copy the identical map.
Two 'New Bookings' message styles share one channel
A successful evaluation/intro booking and a failed one both land in the #New Bookings channel - the only difference is the message heading ('FYI, New Booking:' vs 'FYI, New Booking, Payment Failed:').
Bot identity varies by alert
Some alerts post as a named bot (Membership Bot, Coach Digest Bot, Comms Bot); others post through a personal Cliq connection and show up under a staff member's own name (Bijoy Persie, Max Persson) rather than a bot.
Dunning alerts have an email fallback
sfaDunningTeamAlert is designed so that if a bot DM can't be resolved for a salesperson, it falls back to a direct Cliq DM from Max's own account, and if that path fails too, Max receives an emailed copy of the case list as a fallback.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (21)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
SalePOS_Cliq_Notificationn/a | flow | Active last run 2026-09-22 (live | POS/Commerce invoice created invoice rate > 250 AED | Posts service, amount, customer email/name, salesperson and location to Cliq channel unique name 'paygsales' (#PAYG Sales) via zoho.cliq.postToChannel. | Zoho Flow > Zoho POS/Commerce Flows > Zoho POS/Commerce - GOLF MANAGER arch/flow_deluge_source/SalePOS_Cliq_Notification.deluge |
CRM_UpdatePayStatus_GMBookingCreationn/a | function | Code last run unknown (no per- | called from a Checkout-to-CRM/GM flow on successful Intro to Golf payment none beyond a resolved contact + pending Evaluation_Booking | Confirms the booking in CRM, creates the GolfManager booking + credit + payment, updates CRM credits, then posts 'FYI, New Booking:' to Cliq channel unique name 'zohobookingsm' (#New Bookings). | Zoho Flow > Zoho Checkout - Zoho CRM arch/flow_deluge_source/CRM_UpdatePayStatus_GMBookingCreation.deluge |
ZCRM_UpdatePaymentStatus_GMBookingCreationn/a | function | Code last run unknown | called from a Checkout-to-CRM/GM flow on successful Golf Swing Evaluation payment same as CRM_UpdatePayStatus_GMBookingCreation, near-duplicate logic | Same booking/credit/payment chain for GolfSwing Evaluation, posts 'FYI, New Booking:' to 'zohobookingsm' (#New Bookings). | Zoho Flow > Zoho Checkout - Zoho CRM arch/flow_deluge_source/ZCRM_UpdatePaymentStatus_GMBookingCreation.deluge |
Zcliq_PaymentFailed_Golf_Swing_Evaluationn/a | function | Code last run unknown | called on failed Golf Swing Evaluation checkout payment matching pending Evaluation_Booking found for the contact | Posts 'FYI, New Booking, Payment Failed:' with appointment/customer/coach detail to Cliq channel 'zohobookingsm' (#New Bookings). | Zoho Flow > Zoho Checkout - Zoho CRM arch/flow_deluge_source/Zcliq_PaymentFailed_Golf_Swing_Evaluation.deluge |
ZcliqMsg_PaymentFailed_intro_to_golf_n/a | function | Code last run unknown | called on failed Intro to Golf checkout payment matching pending Evaluation_Booking found for the contact | Same as Zcliq_PaymentFailed_Golf_Swing_Evaluation but for Intro to Golf; posts to the same 'zohobookingsm' channel. | Zoho Flow > Zoho Checkout - Zoho CRM arch/flow_deluge_source/ZcliqMsg_PaymentFailed_intro_to_golf_.deluge |
NOSHOW Internal Alert6296422000047316082 | workflow rule | Inactive last run 2026-08-30T10:53 | field update, Noshow_Flag = 'No-show' Noshow_Flag equals No-show | Calls sfanoshowalert: posts to the coach's own Cliq chat (name-matched via hardcoded map: Richard/Stian/Harry/Pradeep/Brad) and to a fixed Member Success chat (chat_id 2243163332205397868, Akash Thangadore's DM). Full detail in the no-show flow. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfanoshowalert.deluge |
Coach Pre-Session Briefing Sweep6296422000051420046 | workflow rule | Active last run 2026-10-11T10:01 | date_or_datetime, 1 day before Start_Date_and_Time, execute_at 10:00:00+04:00 none beyond the date offset | Calls sfaEvalBriefingSendTest, which resolves the coach (Coach_Name or parsed from linked Bookings.Resource_Name) via a hardcoded chatMap (Richard/Stian/Harry/Pradeep/Brad/Henry -> Cliq chat id) and posts a 'BEFORE YOU WALK IN' message with player name, session time, intake status and a Game Plan Builder link (system.swingfitacademies.com/coaches/game-plan.html) to that chat. | CRM Setup > Automation > Schedules (date-based on Evaluation_Booking) arch/crm_deluge_source/sfaevalbriefingsendtest.deluge |
Coach Post-Session Debrief Send6296422000052132373 | workflow rule | Active last run 2026-10-11T16:00 | date_or_datetime, 0 days after End_Date_and_Time none beyond the date offset | Calls sfaEvalDebriefSend, same chatMap as the briefing sweep, posts an 'EVAL DEBRIEF' message with a prefilled Zoho Forms 'Eval Debrief' formperma link (Field Alias prefill, 12 fields) to the coach's chat. | CRM Setup > Automation > Workflow Rules (date-based on Evaluation_Booking) arch/crm_deluge_source/sfaevaldebriefsend.deluge |
sfadunningteamalert6296422000047169009 | schedule | Active last run 2026-09-02 (arch | daily 09:00 Zoho Billing subscription status PAST_DUE or UNPAID, minBalance 100.0, across both orgs (872210045 DIFC, 866469739 Studio City) | Buckets cases by salesperson (hardcoded name-to-email map), resolves each salesperson's Cliq user id, DMs the case list via bot 'membershipbot' (chunked at ~3800 chars), falls back to a direct buddy DM then to an emailed copy to Max if the bot DM can't be resolved. Unmapped salespeople and warnings go to Max separately. | CRM Setup > Automation > Schedules arch/crm_deluge_source/sfadunningteamalert.deluge |
ZForms - ZCliq/Announcementsn/a (link_name not captured for this exact flow name) | flow | On last run unknown | Zoho Forms entry submitted none | Calls ZForms_ZCliqAnnouncement, which posts a formatted message (mst/coach/player_email/eva_con/reason) to Cliq chat id CT_2243197621731697161_866431816 - confirmed live as the #Announcements channel. | Zoho Flow > Zoho Forms - Zoho Cliq arch/flow_deluge_source/ZForms_ZCliqAnnouncement.deluge |
Cliq Notification469029000000366008 | flow | On last run unknown | Zoho Creator record created none captured | Uses Zoho Flow's native 'Message in channel' Cliq action (zoho_cliq_post_a_message_to_channel) to post about a new pause request. Target channel not visible in the captured node config. | Zoho Flow > Zoho Creator Pause n/a - native connector action, no Deluge source |
Cliq Notification Cancel469029000000366041 | flow | On last run unknown | Zoho Creator record created (cancel form) none captured | Same native 'Message in channel' action as 'Cliq Notification', for a pause cancellation. | Zoho Flow > Zoho Creator Pause n/a - native connector action |
PracticePassesCliqNotificationn/a | function | Code last run 2026-09-07 (live | subscription/purchase event (subscriptionID, inc_org_id) none captured beyond a resolved product/plan | Posts product name, plan name, customer email/name and location to Cliq channel unique name 'practicepasses' (#Practice Passes) via zoho.cliq.postToChannel. | Zoho Flow function, called from a Practice Passes purchase flow arch/flow_deluge_source/PracticePassesCliqNotification.deluge |
sfaWhatsAppStaleSweep6296422000051896772 (schedule) | function | Active last run 2026-09-02 (arch | hourly/every2h WhatsApp_Notify_States unresolved 10+ minutes, guarded by Notified_Stale | Posts a stale-conversation nudge to Cliq chat id CT_1608784870891293581_866431816 (#Inbound WhatsApp) with bot_unique_name=commsbot. | CRM Setup > Automation > Schedules arch/crm_deluge_source/sfawhatsappstalesweep.deluge |
sfaDailyGuestReport6296422000051579026 | schedule | Active last run 2026-09-23 (live | daily 08:00 none beyond the day's group-class attendee list | Emails a member/guest signup digest and posts the same text via Membership Bot to Cliq channel unique name 'eventupdates' (#Event Updates), using zoho.cliq.channelsbyname with bot_unique_name=membershipbot; prefixes a test marker to the message when testMode is on. | CRM Setup > Automation > Schedules arch/crm_deluge_source/sfadailyguestreport.deluge |
sfaCoachMorningDigest6296422000046337495 | schedule | Active last run 2026-09-02 (arch | daily 07:30 coach's bookings for the day | Calls zoho.cliq.postToBot('coachdigestbot', msgMap, 'cliq_connection') with the coach's email as userids; live output seen carries a test-mode prefix naming the intended recipient instead of reaching the coach directly. | CRM Setup > Automation > Schedules arch/crm_deluge_source/sfacoachmorningdigest.deluge |
sfaCoachEODNudge6296422000046337537 | schedule | Active last run 2026-09-01 (arch | daily 20:00 coach's missing lesson reports for the day | Same postToBot('coachdigestbot', ...) mechanism as the morning digest, addressed by coach email. | CRM Setup > Automation > Schedules arch/crm_deluge_source/sfacoacheodnudge.deluge |
sfaSameDayBookingPing6296422000046337517 | workflow rule | Active last run 2026-10-12T06:20 | create, Bookings record Status != Cancelled, Start date = today, current time > 07:30 (to avoid double-notifying with the morning digest), Resource_Name matches one of 5 hardcoded coach resource lists | Builds a prefilled LessonReport form link and posts 'New same-day booking, coach:' via postToBot('coachdigestbot', ...) addressed by the matched coach's email. | CRM Setup > Automation > Workflow Rules > Bookings arch/crm_deluge_source/sfasamedaybookingping.deluge |
sfaEvalIntakeBackstop6296422000052315007 | schedule | Active last run 2026-09-02 (arch | hourly/every2h Evaluation_Booking due <=24h out, per the R0/R1/R2 eval-intake-pipeline S2.3 backstop logic | Posts a 'Member Success call list -- N eval(s) added, <=24h out' digest to Cliq chat id CT_1608784878867032616_866431816 (#Member Success - Roadmap Gaps). | CRM Setup > Automation > Schedules arch/crm_deluge_source/sfaevalintakebackstop.deluge |
sfaCreateLessonReportn/a (standalone function, no workflow-rule association found) | function | Code last run unknown | form/app submit (standalone.sfaCreateLessonReport) player's score crosses the threshold for their next roadmap level | Creates the lesson report, updates Member_Plan progress, and on a level-up posts a Cliq message to a resolved coach chat id (notifyChatId). | Called from the Lesson Report form/app submission path arch/crm_deluge_source/sfacreatelessonreport.deluge |
sfaLogRoundn/a | function | Code last run unknown | round-logging submission player's score crosses a roadmap-level threshold | Same level-up Cliq notification pattern as sfaCreateLessonReport, posted via the zohocliq connection to a resolved chat id. | Zoho Flow function arch/flow_deluge_source/sfaLogRound.deluge |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Bookings | Noshow_Flag | Set to 'No-show' or 'Late-Cancel' to trigger the no-show Cliq alert (covered fully in the no-show flow) | GolfManager sync / sfaMarkNoShow button (see no-show flow) |
| Evaluation_Booking | Coach_Name | Primary coach lookup used by the pre-session briefing and post-session debrief chat-ID map | GolfManager/CRM booking sync |
| Evaluation_Booking | Intake_completed | Whether pre-session intake was done; drives which briefing text sfaEvalBriefingSendTest sends | Intake flow / form |
IDs and references
| What | Value |
|---|---|
| Cliq channel: #PAYG Sales | CT_1423996550947968984_866431816 (unique name: paygsales) |
| Cliq channel: #New Bookings | CT_1424569691894954897_866431816 (unique name: zohobookingsm) |
| Cliq channel: #Event Updates | CT_1608784871704750164_866431816 (unique name: eventupdates) |
| Cliq channel: #Practice Passes | CT_1424665044593910974_866431816 (unique name: practicepasses) |
| Cliq channel: #Inbound WhatsApp | CT_1608784870891293581_866431816 |
| Cliq channel: #Member Success - Roadmap Gaps | CT_1608784878867032616_866431816 |
| Cliq channel: #Announcements | CT_2243197621731697161_866431816 |
| Cliq channel: #Payment Failure & Card Removals (unused by these flows) | CT_1608777526877909035_866431816 |
| Cliq bot: Coach Digest Bot | CT_1423996536144630665_866431816-B2 / bot_unique_name coachdigestbot |
| Cliq bot: Membership Bot | CT_1424735395056297236_866431816-B2 / bot_unique_name membershipbot |
| Coach DM chat-id map (Richard/Stian/Harry/Pradeep/Brad/Henry) | Richard 2204020563142583553, Stian 1608865434731246822, Harry 1608865438891538967, Pradeep 1424464136569307405, Brad 2231781609692944692, Henry 1424577083786594385 |
| Fixed 'Member Success' DM target in the no-show alert | 2243163332205397868 (Akash Thangadore's personal Cliq DM chat) |
All flows › WhatsApp
How WhatsApp works for us
One WhatsApp Business number runs through Zoho CRM (Meta Cloud API) for approved-template sends and through SalesIQ/Cliq for inbound routing; several planned legs are not live yet.
- Starts when
- Either (a) a CRM Workflow Rule's criteria are met and it fires a WhatsApp Notification action referencing an approved template, or (b) a lead/member sends an inbound WhatsApp message to the shared business number.
- Covers
- How SwingFIT sends and receives WhatsApp messages end to end: the number/connection, consent, template approval, which automations fire outbound sends today, and where inbound replies land. Does not cover Google review requests (see the reviews flow) or Backstage event messaging.
- Systems
- Zoho CRM, WhatsApp, Zoho Cliq
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- n/aThe number & connectionZoho CRM
One WhatsApp Business number, run through CRM's native Meta integration
Verified liveSwingFIT's WhatsApp Business number is connected to Zoho CRM (Setup > Channels > WhatsApp, Meta Cloud API under the hood) and to Zoho SalesIQ under the same Zoho One account, so inbound and outbound share one number. Templates are authored in Setup > Automation > Actions > WhatsApp Notifications and submitted to Meta for approval from inside CRM.
See itCRM Setup > Channels > WhatsApp; CRM org 866442566. - n/aConsent captureZoho CRM
WhatsApp marketing consent is tracked separately from being a customer
From codeThree fields on Contacts (WA_Marketing_Consent, WA_Marketing_Consent_Date, WA_Marketing_Consent_Revoked_Date) track whether a lead/member has opted into WhatsApp marketing sends. swingfit_wa_optin_confirm stamps consent true when a web-form/booking checkbox fires. sfawastophandler is a webhook target for SalesIQ's Data Workflow: an inbound message containing the word STOP is matched to the Contact by phone and revokes consent.
- The opt-in gate itself (W8) is built but switched offFrom coden/a
A Workflow Rule fires the ic_whatsapp_optin_confirm template on new Player/Lead creation, built and left inactive pending a go-live decision. No lead or member is currently opted in through this path.
See itContact record > WA_Marketing_Consent field; Setup > Developer Hub > Functions > sfawastophandler. - n/aTemplate approvalZoho CRM
Every template is written, categorized Utility or Marketing, and Meta-approved before it can send
Verified liveTemplates go through Meta review from inside CRM's WhatsApp Notifications screen. Utility templates (booking/session logistics, tied to a specific transaction) get simpler review; anything promotional must be classed Marketing. A prefix naming scheme (ic_/bk_/ms_/ev_) groups templates in CRM's flat alphabetical picker.
See itCRM Setup > Automation > Actions > WhatsApp Notifications > WhatsApp Templates. - n/aOutbound sendsZoho CRM
Approved templates fire only from CRM Workflow Rules -- never sent by hand, never sent from Zoho Flow or Marketing Automation
Verified liveThe standing team rule is: templates go out from CRM only, triggered by a Workflow Rule's WhatsApp Notification action, with merge fields resolved from the record. Live examples include booking/session logistics (bk_ templates), membership lifecycle nudges (ms_ templates, most gated behind the inactive consent opt-in above), and graduation comms.
See itCRM Setup > Automation > Workflow Rules; open a rule's Instant Actions to see if a WhatsApp Notification is attached. - n/aLead-side WhatsApp nudgesZoho CRM
New-lead WhatsApp nudges exist by design but are currently switched off
UnverifiedA set of Leads-module rules are designed to send a first WhatsApp message and notify staff the moment a lead is created or edited (a standard new lead, a beginner-lead variant, and a paid-ads variant).
See itCRM Setup > Automation > Workflow Rules, module Leads -- rule names currently carry a ZZOFF-2026-09 prefix and show Status: Inactive. - n/aGraduation commsZoho CRM
A daily schedule sends graduation-moment nudges, WhatsApp included
Verified livesfagradcomms runs daily, scans Member_Plan for a graduation-pending flag, and sends a same-day congratulations plus Day-3 and Day-7 nudges. The Day-3 nudge is Marketing-classed; an early Day-7 version was rejected by Meta as miscategorized Utility and replaced with a Marketing-classed version.
See itCRM Setup > Automation > Schedules > sfagradcomms. - n/aNo-show follow-upZoho CRM
A no-show is designed to eventually get a WhatsApp follow-up after the policy-reminder email
UnverifiedThe no-show policy-reminder function stamps a Bookings field (Noshow_WA_Stage) to mark a record as ready for a WhatsApp follow-up leg, alongside its email leg.
See itBookings record > Noshow_WA_Stage field. - n/aInbound routingZoho Cliq
An inbound WhatsApp message posts a staff alert, gets deduplicated, and is swept if it goes unanswered
Verified liveA workflow posts new inbound WhatsApp/SalesIQ conversations to a Cliq channel via a dedicated bot, keeping a CRM ledger to avoid re-pinging the same open conversation. A separate check resolves that ledger state when a staff operator replies. A schedule sweeps for messages that have sat unanswered and posts a reminder ping, currently on a 2-hour cycle (the platform's UI floor, not the originally designed 10 minutes).
- A separate, older rule also pings on a brand-new lead's first messageVerified liven/a
A separate rule also posts to a Cliq channel the moment a brand-new Lead record is created, running alongside the sweep above.
See itCliq channel #Inbound WhatsApp : @Member Success; CRM module WhatsApp_Notify_States (CustomModule38). - n/aReplies land in CRMZoho CRM
Member and lead replies route into CRM's Messages module, not a phone
Verified liveInbound WhatsApp traffic lands in CRM's Messages module (the messages__s object) where staff read and reply. The physical WhatsApp Business handsets are being phased out as a surface once every inbound/outbound path is proven to run through CRM/SalesIQ.
See itCRM > Messages module. - n/aManual sendZoho CRM
Staff can also send an approved template by hand from a Player record
Verified liveOn a Player (Contacts) record, the small dropdown arrow next to the Send Email button opens Send WhatsApp Template -- a searchable, previewed list of approved templates. Leads have no equivalent option; a Lead must be converted to a Player first, because the branded Lead Canvas view doesn't expose the same control.
See itAny Player record > the dropdown next to Send Email.
Emails and messages
Customeric_ic_booking_abandonUnverifiedn/a (WhatsApp)
Full text (crm_email_templates/WhatsApp-Template-Register-2026-08-19.html)
Customerbk_session_confirm_or_cancelUnverifiedn/a (WhatsApp)
Full text (crm_email_templates/WhatsApp-Template-Register-2026-08-19.html)
Customerms_ms_grad_day7_nudge_v2Unverifiedn/a (WhatsApp)
Full text (crm_email_templates/WhatsApp-Template-Register-2026-08-19.html)
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Is a new lead getting a WhatsApp nudge right now? | CRM Setup > Automation > Workflow Rules, module Leads | A rule without a ZZOFF prefix, Status: Active |
| Has a member actually consented to WhatsApp marketing? | Player record > WA_Marketing_Consent field | Checkbox true with a consent date stamped |
| Did an inbound WhatsApp message get missed? | Cliq channel #Inbound WhatsApp : @Member Success | A ping from Comms Bot within roughly 2 hours of the message |
| Is a WhatsApp template actually approved and usable? | CRM Setup > Automation > Actions > WhatsApp Notifications > WhatsApp Templates | Status column reads Approved, not In Review or Failed |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| WhatsApp marketing to one member/lead | Player/Lead record > WA_Marketing_Consent, or they text STOP | sfawastophandler revokes consent and stamps the revoke date; future Marketing-class sends should stop reaching them |
| The stale-message Cliq sweep | CRM Setup > Automation > Schedules > sfaWhatsAppStaleSweep | No more reminder pings for unanswered inbound WhatsApp messages |
| A specific outbound template rule | CRM Setup > Automation > Workflow Rules > that rule > toggle inactive | That one message stops firing; the template itself stays approved and reusable elsewhere |
Good to know
Templates group by name, not by a real CRM category
Zoho's WhatsApp template picker is a flat alphabetical list, so a naming prefix (ic_ Initial Contact, bk_ Booking & Logistics, ms_ Membership Sales & Lifecycle, ev_ Events) is the only structure available.
The SFA WhatsApp History folder is an export archive, not a live system
A folder of per-contact WhatsApp chat exports (zip files) sits in the AI OS for reference -- it was used to study what staff were manually typing before templates existed, informing which templates to build. It is historical research material, not a connected system, and its contents are personal message archives.
Service replies inside an open 24-hour window don't need a pre-approved template
Once a lead/member has messaged in, a free-form reply is allowed for 24 hours; after that window, only a pre-approved template can restart the conversation.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (15)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
swingfit_wa_optin_confirm | function | Active | Called from a web-form/booking-flow checkbox (W8 journey) n/a | Writes WA_Marketing_Consent=true and stamps WA_Marketing_Consent_Date on the Contact. The WhatsApp confirmation send itself is a TODO placeholder, never filled in. | Setup > Developer Hub > Functions crm_email_templates/flows_bookings/SFA-Functions-PasteSheet.md #18 |
sfawastophandler | function | Active | Webhook from SalesIQ's Data Workflow on an inbound WhatsApp message Message body contains the word STOP | Looks up the Contact by phone, sets WA_Marketing_Consent=false and stamps WA_Marketing_Consent_Revoked_Date. | Setup > Developer Hub > Functions (REST-enabled) crm_email_templates/flows_bookings/SFA-Functions-PasteSheet.md #18 |
W8 - WhatsApp opt-in confirmation on new Player/Lead creation6296422000051316025 | workflow rule | Inactive | Contacts create none (fires on every new Player/Lead) | Fires WhatsApp Notification action referencing ic_whatsapp_optin_confirm. | CRM Setup > Automation > Workflow Rules > Contacts n/a |
ZZOFF-2026-09 Send WA 16296422000003305002 | workflow rule | Inactive last run 2026-01-27T10:38 | Leads create_or_edit none captured in this pass | Sends first WA message to a new lead. | CRM Setup > Automation > Workflow Rules > Leads n/a |
ZZOFF-2026-09 Send WA Intro6296422000003318020 | workflow rule | Inactive last run 2025-07-23T10:53 | Leads create_or_edit Beginner lead variant | Sends first WA to a beginner lead. | CRM Setup > Automation > Workflow Rules > Leads n/a |
ZZOFF-2026-09 Send WA 1 LGE6296422000009693001 | workflow rule | Inactive last run 2025-09-17T17:40 | Leads create_or_edit Long Game Eval lead variant | Sends first WA to a Long Game Eval lead. | CRM Setup > Automation > Workflow Rules > Leads n/a |
ZZOFF-2026-09 Send WA 1 Membership6296422000021720001 | workflow rule | Inactive last run 2026-01-27T17:44 | Leads create_or_edit Membership-ad lead variant | Sends first WA to a lead. | CRM Setup > Automation > Workflow Rules > Leads n/a |
ZZOFF-2026-09 New Lead WA Notify6296422000006965001 | workflow rule | Inactive last run 2026-09-08T13:26 | Leads create_or_edit none | Sends a WhatsApp message to the Member Success team notifying them of a new lead. | CRM Setup > Automation > Workflow Rules > Leads n/a |
ZZOFF-2026-09 WA Message Sent6296422000002745048 | workflow rule | Inactive last run 2025-05-26T15:52 | Leads field_update (WA_Sent) WA_Sent changes | Stamps a status field after a WA message goes out. | CRM Setup > Automation > Workflow Rules > Leads n/a |
sfagradcomms | schedule | Active | Daily Member_Plan.Graduation_Pending = true | Sends same-day congratulations plus Day-3 and Day-7 nudges (email + WhatsApp) on graduation moments. | CRM Setup > Automation > Schedules automation/orphan-sweeps/sfagradcomms-2026-08-17.md (description only; full function body not saved to a code home) |
sfanoshowpolicyreminder | function | Inactive | Bookings field_update on Noshow_Flag Noshow_Flag is No-show or Late-Cancel, member-tier player, only once | Sends the no-show policy-reminder email and stamps Noshow_WA_Stage='Pending - WA push' for a WhatsApp follow-up that has not been built. | Setup > Developer Hub > Functions (no code home) crm_functions_live/functions/sfanoshowpolicyreminder.deluge |
WhatsApp dedup/reopen (Part A) | function | Active | conversation.created / conversation.visitor.replied No open WhatsApp_Notify_States ledger row for the conversation | Posts a Cliq alert for a new/reopened inbound WhatsApp conversation via the Comms Bot; writes a ledger row to suppress repeat pings. | SalesIQ Data Workflow script n/a |
WhatsApp Operator Reply Resolves State (Part C) | function | Active | A staff operator replies in the conversation n/a | Marks the WhatsApp_Notify_States ledger row resolved so the next inbound message re-opens cleanly. | SalesIQ / CRM script n/a |
sfaWhatsAppStaleSweep | schedule | Active | Every 2 hours (platform floor; 10-minute cadence was the original design) messages__s: conversation_status__s not Responded/Replied, sender__s is inbound, message_time__s older than the stale window | Posts a reminder ping to Cliq for a WhatsApp message that has sat unanswered. | CRM Setup > Automation > Schedules n/a |
Jan 2026 New Lead Notification6296422000029070009 | workflow rule | Inactive last run 2026-09-08T13:26 | Leads create Lead_Status == 'New Lead' | Posts to Cliq channel #New Lead Notification via a cliq_notifications action. | CRM Setup > Automation > Workflow Rules > Leads n/a |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Contacts | WA_Marketing_Consent | Whether this lead/member has opted into WhatsApp marketing sends | swingfit_wa_optin_confirm (true) / sfawastophandler (false, on STOP) |
| Contacts | WA_Marketing_Consent_Date | When consent was given | swingfit_wa_optin_confirm |
| Contacts | WA_Marketing_Consent_Revoked_Date | When consent was revoked | sfawastophandler |
| Bookings | Noshow_WA_Stage | Marks a no-show record ready for a WhatsApp follow-up leg | sfanoshowpolicyreminder |
| Leads | WA_Sent | Legacy flag for the 2025 WhatsApp drip; superseded by WhatsApp_Notify_States for the live inbound cluster | the ZZOFF-2026-09 WA Message Sent rule |
Full email text
ms_ms_grad_day7_nudge_v2n/a (WhatsApp)
bk_bk_pretee_go_or_canceln/a (WhatsApp)
IDs and references
| What | Value |
|---|---|
| CRM org | 866442566 |
| Zoho Marketing Automation org | 868822291 |
| WhatsApp_Notify_States module | CustomModule38 |
| Inbound WhatsApp Cliq Notification workflow | 956257000001475001 |
| Cliq channel #New Lead Notification | O5766196000001162001 |
| Dedicated Cliq bot | commsbot (Comms Bot) |
All flows › Zoho Bookings sync
How Zoho Bookings and GolfManager stay in step
Zoho Bookings has been retired as a live booking surface; GolfManager plus the in-house SwingFIT app are the real source of truth, but one public page still links to the old system.
- Starts when
- Historically: a customer booking a slot on a Zoho Bookings page, or a coach blocking time off via a Zoho Form. Per Max (confirmed 2026-09-07), Zoho Bookings itself is retired and no longer the live path - the trigger today is either the in-house SwingFIT booking app or a direct GolfManager tee-sheet booking.
- Covers
- Covers the two Flow folders built around Zoho Bookings ('Zoho Bookings - Golf Manager' and 'Zoho Bookings - Zoho Books / Zoho Cliq / Zoho CRM') and what actually creates a booking today. Does not cover the GolfManager<->CRM booking sync that runs independently of Zoho Bookings (see the eval-booking and lesson-booking flows).
- Systems
- Zoho Bookings, GolfManager, Zoho Flow, Zoho Forms, Zoho CRM, Zoho Books, Cliq, Website
Journey map
Numbers match the steps below. On a phone, scroll the map sideways.
Step by step
- historicalZoho Bookings retiredZoho Bookings
Zoho Bookings was replaced by the in-house SwingFIT booking app
Verified livePer Max (2026-09-07), Zoho Bookings is no longer used to create real bookings. The in-house SwingFIT booking app (built by Bijoy) creates
Evaluation_Bookingrecords directly via an external REST call to the CRM v8 API - not through Zoho Flow or a Deluge function - so these records carrySource = "App"and are attributed to Bijoy's CRM user rather than to a customer-facing web flow.See itZoho CRM > Evaluation_Booking module > filter Source = App - T+0 (webhook)GolfManager to Zoho Bookings availability pushGolfManager
A webhook from GolfManager is designed to push coach availability/blocking into Zoho Bookings
From codeGMBooking_to_Zbookings(Flow, folder 'Zoho Bookings - Golf Manager', webhook trigger) callsUpdateZBookings_from_GM, which takes a coach id, a time window and a reason and is designed to block that window on the matching Zoho Bookings staff calendar.See itZoho Flow > 'Zoho Bookings - Golf Manager' folder > 'GMBooking_to_Zbookings' - T+0 (form submit)Coach time-off form to Zoho Bookings + GolfManagerZoho Forms
A coach submitting a time-off form is designed to block the same window in both Zoho Bookings and GolfManager
From codeBlocking_FORMS_ZBOOKINGS_GM(Flow, same folder, Zoho Forms 'Entry submitted' trigger) callsUpdate_ZBookings_GM_FROM_FORMS, which parses the coach, the from/to window and a reason from the form and writes the block to both systems.See itZoho Flow > 'Zoho Bookings - Golf Manager' folder > 'Blocking_FORMS_ZBOOKINGS_GM' - T+0 (webhook, unopenable)Zoho Bookings appointment into GolfManagerZoho Bookings
A Zoho Bookings appointment was designed to create the matching booking, invoice and CRM status update
UnverifiedZBOOKING_TO_GOLFMANAGER(Flow, same folder) is one of the flows Zoho Flow's own configuration API cannot open (see the estate-wide 'flows that won't open' finding). Its two candidate functions areUpdateGMBookings_from_Zbookings(pulls the Zoho Bookings appointment and creates the matching GolfManager booking) andPushGMINV_Creator_UpdateCRMBookingStatus(reads the resulting GolfManager invoice and writes its number/date back onto the CRM record).See itZoho Flow > 'Zoho Bookings - Golf Manager' folder > 'ZBOOKING_TO_GOLFMANAGER' (will not open) - T+0 (webhook, unopenable, all 4 flows)Bookings-to-Books/Cliq/CRM fan-outZoho Bookings
Four more flows were designed to fan a Zoho Bookings appointment out to Books, Cliq and CRM
UnverifiedAll four flows in the 'Zoho Bookings - Zoho Books / Zoho Cliq / Zoho CRM' folder are on the estate's list of 29 flows Zoho Flow's own configuration API cannot open:
ZohoBookings_to_ZohoBooks(candidate functions include GM_ZCRM_BookingCreate_Upsert, SubscriptionINV_Creator, UpdateCreditsInCRM_FromPOS, UpdateCreditsinCRM_based_on_GMInvoices, UpdateMembershipCredits_CRM_SubscriptionInv, UpdateZbooksINVPAY_ZBookings - which pulls a Zoho Bookings appointment, maps its workspace/service to a Zoho Books org and line item, and files the payment),Zoho Bookings to Player in CRM(callsUTM_CRM_PLAYERS_Payment_Sucess, an exact-match candidate, which pulls UTM fields off the appointment's custom fields onto the matching CRM contact),ZBookings to CRMPlayer - Payment Failed(candidates Create_HostedPage_ZBillings, UTM_CRM_PLAYERS_Payment_Failed) andZoho Bookings Payment Failure(no candidate function found in the archive at all).See itZoho Flow > 'Zoho Bookings - Zoho Books / Zoho Cliq / Zoho CRM' folder (none of the 4 flows will open) - T+0 (real time, live path today)Live path: GolfManager tee sheet to CRMGolfManager
The booking that actually keeps CRM in step today comes straight from GolfManager, not Zoho Bookings
Verified liveNew Bookings and Evaluation_Booking records are created continuously from two live sources: the in-house SwingFIT app (Source = App) and a direct GolfManager sync (Source = GolfManager). A same-morning check of the Bookings module found records created every few minutes, all attributed to the GolfManager sync integration user, with none sourced from Zoho Bookings.
See itZoho CRM > Bookings / Evaluation_Booking modules > sort by Created Time
Where to check
| Question | Look here | What working looks like |
|---|---|---|
| Is a given booking coming from the app or from GolfManager? | Zoho CRM > Evaluation_Booking (or Bookings) > the record's Source field | Source reads 'App' or 'GolfManager' - never 'Zoho Bookings' on anything created recently |
| Does the public evaluation page still point at Zoho Bookings? | swingfitacademies.com/golf-swing-evaluation/ - inspect the booking CTA's link target | The CTA should point at the in-house SwingFIT booking app, not at a zbooking.us short link |
How to switch it off
| Part | Where the switch is | What stops |
|---|---|---|
| GolfManager-to-Zoho-Bookings availability push | Zoho Flow > 'Zoho Bookings - Golf Manager' folder > 'GMBooking_to_Zbookings' | Coach time-off/blocking windows raised in GolfManager stop reaching Zoho Bookings |
| Coach time-off form dual-block | Zoho Flow > 'Zoho Bookings - Golf Manager' folder > 'Blocking_FORMS_ZBOOKINGS_GM' | A coach's time-off form submission stops blocking the window in Zoho Bookings and GolfManager |
Good to know
Zoho Bookings is retired, not just quiet
Max confirmed on 2026-09-07 that Zoho Bookings has been fully replaced by the in-house SwingFIT booking app for live session and evaluation booking - it is not expected to create real bookings any more.
The in-house app writes straight to the CRM API
The SwingFIT booking app creates Evaluation_Booking records via a direct external REST call to the CRM v8 API rather than through Zoho Flow or a Deluge function, which is why these records carry a different Created_By and Source than everything else in this folder.
GolfManager resource IDs identify the location
Records created by the app carry GolfManager resource ids 155 (Studio City) and 156 (DIFC) in Resource_Id/Resource_Type_Id, and the GolfManager resource string (e.g. 'Coach Henry (Evaluations)') in the record's Name field.
Technical detailevery automation, field and ID behind this flow, and the full text of each email
Automations (13)
| Name | Kind | Status | Trigger and conditions | What it does | Where / code |
|---|---|---|---|---|---|
GMBooking_to_Zbookings469029000000039001 | flow | Enabled last run unknown | webhook none captured | Calls UpdateZBookings_from_GM(from_str, to_str, coach_id, reason_text) to block a coach's window in Zoho Bookings. | Zoho Flow > Zoho Bookings - Golf Manager arch/flow_deluge_source_or_crm/ (function id 469029000000046005), source in flow_functions.json |
UpdateZBookings_from_GM469029000000046005 | function | Live last run unknown | called by GMBooking_to_Zbookings computes an hourly block list between from_str and to_str | Parses the GM time window and pushes a matching block onto the coach's Zoho Bookings staff calendar via the 'zbookings' connection. | Zoho Flow function (mapped to flow 469029000000039001) arch/raw_capture/flow_functions.json (function UpdateZBookings_from_GM) |
Blocking_FORMS_ZBOOKINGS_GM469029000000039043 | flow | Enabled last run unknown | Zoho Forms 'Entry submitted' none captured | Calls Update_ZBookings_GM_FROM_FORMS(coach, from_raw, to_raw, reason_text) to block the same window in both Zoho Bookings and GolfManager. | Zoho Flow > Zoho Bookings - Golf Manager flow function id 469029000000039109 |
Update_ZBookings_GM_FROM_FORMS469029000000039109 | function | Live last run unknown | called by Blocking_FORMS_ZBOOKINGS_GM parses coach name, from/to raw strings | Computes the block window and writes it to Zoho Bookings and GolfManager for the named coach. | Zoho Flow function (mapped to flow 469029000000039043) arch/raw_capture/flow_functions.json (function Update_ZBookings_GM_FROM_FORMS) |
ZBOOKING_TO_GOLFMANAGER469029000000049011 | flow | Listed last run unknown | webhook (candidate; flow config not readable) unknown - flow is on the estate's 29 flows Zoho Flow's configuration API cannot open (returns 'Request was formatted incorrectly'; 404s in the Flow web app) | Candidate functions (ambiguous match, truncated-id collision): UpdateGMBookings_from_Zbookings (pulls a Zoho Bookings appointment via getappointment, creates the matching GolfManager booking) and PushGMINV_Creator_UpdateCRMBookingStatus (reads the resulting GolfManager invoice, writes invoice number/date back onto the CRM record). | Zoho Flow > Zoho Bookings - Golf Manager arch/raw_capture/flow_functions.json (functions 469029000000046063, 469029000000055083) |
UpdateGMBookings_from_Zbookings469029000000046063 | function | Mapped last run unknown | called with a booking_id none captured | GETs the Zoho Bookings appointment (zbookings connection), then POSTs a matching booking to GolfManager (eu.golfmanager.com/api/model, tenant swingfit). | Zoho Flow function, candidate for ZBOOKING_TO_GOLFMANAGER arch/raw_capture/flow_functions.json |
ZohoBookings_to_ZohoBooksn/a (in Zoho Bookings - Zoho Books/Cliq/CRM folder) | flow | Listed last run unknown | webhook (candidate; flow config not readable) one of the estate's 29 unopenable flows | Candidate functions (ambiguous): GM_ZCRM_BookingCreate_Upsert, SubscriptionINV_Creator, UpdateCreditsInCRM_FromPOS, UpdateCreditsinCRM_based_on_GMInvoices, UpdateMembershipCredits_CRM_SubscriptionInv, UpdateZbooksINVPAY_ZBookings. | Zoho Flow > Zoho Bookings - Zoho Books / Zoho Cliq / Zoho CRM arch/raw_capture/flow_functions.json |
UpdateZbooksINVPAY_ZBookings469029000000062201 | function | Mapped last run unknown | called with a booking_id requires a workspace-to-org and service-to-line-item mapping table | GETs the Zoho Bookings appointment, maps its workspace/service to the correct Zoho Books org and line item, and files the payment in Zoho Books. | Zoho Flow function, candidate for ZohoBookings_to_ZohoBooks arch/raw_capture/flow_functions.json |
Zoho Bookings to Player in CRM469029000000209001 | flow | Listed last run unknown | webhook (candidate; flow config not readable) one of the estate's 29 unopenable flows; exact-match candidate function | Calls UTM_CRM_PLAYERS_Payment_Sucess(booking_id): pulls the Zoho Bookings appointment's UTM custom fields (source/medium/campaign/term/content/lead_source) and writes them onto the matching CRM contact. | Zoho Flow > Zoho Bookings - Zoho Books / Zoho Cliq / Zoho CRM flow function id 469029000000216021 |
ZBookings to CRMPlayer - Payment Failed469029000000248072 | flow | Listed last run unknown | webhook (candidate; flow config not readable) one of the estate's 29 unopenable flows | Candidate functions (ambiguous): Create_HostedPage_ZBillings (builds a Zoho Billing hosted-page subscription link) and UTM_CRM_PLAYERS_Payment_Failed (same UTM-capture pattern as the success path, on a failed booking payment). | Zoho Flow > Zoho Bookings - Zoho Books / Zoho Cliq / Zoho CRM arch/raw_capture/flow_functions.json |
Zoho Bookings Payment Failure469029000000192113 | flow | Listed last run unknown | unknown - one of the estate's 29 unopenable flows with no matching Flow function found at all unknown | No Flow function in the archive references this flow by its truncated identifier - its logic, if any, is not recoverable from the archive. | Zoho Flow > Zoho Bookings - Zoho Books / Zoho Cliq / Zoho CRM none found |
SwingFIT booking app (in-house)n/a - not a Flow/CRM automation | other | Live last run 2026-09-22T21:50 | customer books a session/evaluation in the app none | Creates Evaluation_Booking records via a direct external REST call to the CRM v8 API (bypassing Zoho Flow/Deluge entirely), stamping Source='App', Created_By=Bijoy's CRM user, and GolfManager resource ids 155 (Studio City) / 156 (DIFC). | system.swingfitacademies.com (per connections.md); built by Bijoy not in this archive - external app, not documented in the function registry |
Zoho Bookings to Prospects6296422000025959019 | workflow rule | Active last run 2026-09-14T15:20 | Contacts create Lead_Source equals "Zoho Bookings" | Instant field-update action "Empty to prospect" (no custom function) that sets the new Contact's Lifecycle_Status to Prospect whenever the Contact's Lead_Source is Zoho Bookings - i.e. whenever a Zoho Bookings appointment creates a brand-new Contact rather than matching an existing one. | CRM Setup > Automation > Workflow Rules > Contacts n/a (CRM instant field-update action, no Deluge function) |
Key fields
| Module | Field | Meaning | Written by |
|---|---|---|---|
| Evaluation_Booking | Source | Where the booking record originated - 'App' (in-house booking app) or 'GolfManager' (direct GM sync); no 'Zoho Bookings' value seen in a recent sample | SwingFIT booking app / GolfManager sync |
| Evaluation_Booking | Resource_Id / Resource_Type_Id | GolfManager resource identifiers (155 = Studio City, 156 = DIFC) | SwingFIT booking app / GolfManager sync |
| Bookings | Created_By | Recent records all attributed to the GolfManager sync integration user ('Barreto'), consistent with a live GM-to-CRM path rather than a Zoho Bookings webhook | GolfManager sync |
IDs and references
| What | Value |
|---|---|
| Zoho Flow folder: Zoho Bookings - Golf Manager | 469029000000046071 |
| Zoho Flow folder: Zoho Bookings - Zoho Books / Zoho Cliq / Zoho CRM | 469029000000062181 |
| Public CTA link (golf-swing-evaluation) | http://zbooking.us/FaNfO on swingfitacademies.com/golf-swing-evaluation/, resolves through richard-swingfitacademies64.zohobookings.com to a final HTTP 400 |
| Zoho Books orgs | Studio City 866469739, DIFC 872210045 |