Membership passes
How a membership pass is bought, how its balance is stored, how the cart decides which button to show, and what happens when a pass is used.
A membership pass is a prepaid bundle of camps. Buying one sets a balance on the customer's Shopify account. Using one replaces a camp in the cart with a zero-cost copy of that camp, and the balance goes down after checkout.
Buying a pass
Membership pass products are ordinary products listed on the memberships page from the membership-passes collection.
- The customer buys a pass and checks out.
- Zapier's "Membership Pass Purchase via API" zap calls
POST /membershipsonshopify-zoho-integration. - The service creates a Membership Purchase record in Zoho and sets the customer's metafields in the
membership_passnamespace.
| Customer metafield | Meaning |
|---|---|
membership_pass.status | active while the pass can be used |
membership_pass.total_camps | Camps bought |
membership_pass.remaining_camps | Camps left |
membership_pass.redeemed_camps | Camps used |
membership_pass.membership_ids | Zoho membership purchase codes |
The service gives a 3-camp pass 12 months, a 5-camp pass 18 months and a 7-camp pass 24 months, and stores the expiry date on the Zoho Membership Purchase record. A daily Zoho function clears the Is Active flag on expired Zoho records.
The expiry date is not copied to Shopify. The cart and asc-api-membership-pass check only status and remaining_camps, so a pass that has passed its expiry date can still be used unless someone changes status from active.
The cart button
For each camp line, the cart shows one of these states. The logic is in theme/sections/asc-new-cart-layout.liquid.
| Customer | Pass balance | Camp | Button text | Click |
|---|---|---|---|---|
| Logged out | Any | Any | "Login to use membership pass", or the section's Login Text setting | Goes to the login page |
| Logged in | Status not active, or no camps left | Any | "Membership pass not applicable for this camp" | Goes to the account login URL |
| Logged in | Active with camps left | Partner program, or title contains "community sports" | "Membership pass not applicable for this camp" | Explains that passes only apply to camps run by ASC |
| Logged in | Active with camps left | ASC camp | "Use membership pass" | Uses the pass |
| Any | Any | The line is already a pass product | Hidden | None |
A line is treated as a camp when its product is tagged sport.
The partner and Community Sports Camps exclusion is enforced only by this cart logic. asc-api-membership-pass checks the balance but not the camp type.
documentation/MEMBERSHIP.md and documentation/diagrams/membership-pass-cta.svg describe theme/snippets/asc-cart-actions.liquid. That snippet belongs to the previous cart section, which is disabled, and its logged-out behaviour differs from the table above.
Using a pass
- The customer clicks Use membership pass. The browser reads the cart token and sends it, with the customer id, email, variant id and the line's participant properties, to
POST {Google Cloud API URL}v1/customers/{id}/membership-pass/use. asc-api-membership-passchecks that the pass is active and that remaining camps, less any pass products already in the cart, is at least one.- It creates a pass product:
- title "Membership Pass: " followed by the camp's title;
- product type and tag
membership-pass-product, plus the tagsport; - template
product.redirect, which sends anyone who opens it to the home page; - metafield
membership_product.real_productpointing at the original variant; - price $0, one unit of stock, no shipping.
- It swaps the camp line for the pass product in the customer's cart, keeping the participant properties, and builds a copy of the cart with the same change.
- The browser stores the new cart token in the
cartcookie and reloads the page.
Nothing is deducted at this point. After checkout, PUT /memberships on shopify-zoho-integration counts the pass products in the order, reduces remaining_camps and increases redeemed_camps. The zap that makes this call is not named in any repository.
The order line is tagged sport, so POST /orders records it as an ordinary booking in Zoho.
Pass products after checkout
Pass products are hidden from the storefront by the redirect template. A Zapier zap named "Auto-archive membership products" archives them. The zap's trigger and its 15-minute delay are configured in Zapier.
Failure modes
| Symptom | Likely cause |
|---|---|
| "Membership pass not applicable" for a member | status is not exactly active, or remaining_camps is 0 or blank |
| "That didn't work..." after clicking | API rejected the request. The message names the reason, for example "Pass already applied for this line item" |
| Balance not reduced after checkout | PUT /memberships did not run for that order |
| Pass products visible in Products list | Auto-archive zap has not run or is off |
Steps are in The membership pass is not applying.
Pending change
Branch 95-asc-073-fx-au-memberships-revised-cart-messaging-and-info-box in asc-shopify-src, and 96-asc-073-… in the theme repository, changes the cart states. A logged-in customer with no camps left will see "Your account does not have any membership passes left", and partner programs will show as not applicable whatever the balance. Update this page when it merges.
Source map
| Concern | Location |
|---|---|
| Cart button states | theme/sections/asc-new-cart-layout.liquid |
| Button click handlers | src/js/custom.js |
| API root setting | Theme settings, ASC - Membership Pass, Google Cloud API URL (gcloud_api_root) |
| Pass use | asc-api-membership-pass repository, src/services/redemption.service.ts, src/services/pass-product.service.ts |
| Purchase and post-checkout balance | asc-api-src-zoho-integration repository, src/features/membership-pass/ |
| Redirect template | theme/templates/product.redirect.json |