Goal
Turn a regular special offer into an event-style offer that tracks per-user attendance. By the end of this recipe, app users who open the offer will see an “I’m Going” button, the configured venue email gets a “Coming to Event” notification on every RSVP, and each attendee carries a QR confirmation code on their device.
This recipe is for offers that need a guest list — limited-seat tasting, ticketed bar crawl, RSVP-only happy hour. For an offer that just needs to display (“show this screen at the bar for 10% off”), use Recipe: Add a special offer to a listing and skip this recipe.
Prerequisites
- An offer already attached to a listing per Recipe: Add a special offer to a listing
- The venue’s email address (used as the RSVP notification recipient)
- The notification system configured in
mam-mainso notifications can actually be dispatched
How RSVP works
RSVP is gated by a single meta key on the offer post: special-offer-has-rsvp. When that key is non-empty, four things change:
- The offer’s app detail screen renders an “I’m Going” check-in button. It dispatches the
mam_check_inaction on tap, with the offer’s post ID in$_REQUEST['checkinloc']. - The plugin tracks per-user RSVP state in post meta. Each attending user gets a
mam_so_is_going_{user_id}key set toyes, plus a pairedmam_so_is_going_date_{user_id}storing the date they signed up for (sent by the app asthis_date). - A notification fires on RSVP. If
special-offer-rsvp-emailis set on the offer, aspecial-offers-event-rsvpnotification is sent to the user matching that email — push, email, and in-app — withattendee_nameavailable as a replacement. - The offer’s detail screen gains a Confirmation section. The user’s RSVP carries a
wp_create_noncetoken rendered as a QR code under the Confirmation heading. Tapping the button again dispatchesmam_check_into cancel.
There is no native admin UI for these meta keys. They are set programmatically (or via direct meta-box extension), which is what this recipe walks through.
Steps
1. Pick the offer
Find the offer’s post ID. The fastest path is to query for it from the parent listing:
$offers = get_posts( array(
'post_type' => 'special_offers',
'post_status' => 'publish',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => 'special-offer-parent',
'value' => $parent_listing_id,
),
),
) );
foreach ( $offers as $offer ) {
error_log( $offer->ID . ' — ' . $offer->post_title );
}
Note the ID of the offer you want to RSVP-enable.
2. Flip the RSVP flag
Set special-offer-has-rsvp to any non-empty string:
update_post_meta( $offer_id, 'special-offer-has-rsvp', 'yes' );
The plugin only checks for non-emptiness — 'yes', '1', or 'on' all work. We use 'yes' to match the plugin’s other yes/no conventions.
3. Set the notification recipient
The plugin looks up a user by email when an RSVP comes in. Set special-offer-rsvp-email to the venue owner’s WordPress account email:
update_post_meta( $offer_id, 'special-offer-rsvp-email', 'venue-owner@example.com' );
If the email doesn’t match a registered user, the lookup fails silently — the RSVP is still recorded but no notification fires. Confirm the email matches an existing WP_User:
$user = get_user_by( 'email', 'venue-owner@example.com' );
if ( ! $user ) {
// No notifications will be delivered for this offer.
}
4. (Optional) Set seat count
If you want the app to display “Only N left!” on the detail screen, set the Quantity Remaining field. The display value lives in the offer’s special-offer-quantity meta:
update_post_meta( $offer_id, 'special-offer-quantity', '20' );
The plugin counts existing mam_so_is_going_* meta keys when rendering the offer and subtracts that count from the quantity. So a quantity of 20 with 3 RSVPs already in shows “Only 17 left!”.
There’s no enforcement — a user can RSVP even when the quantity reaches zero. The displayed remaining count just becomes negative. If you need a hard cap, gate it in your own callback on mam_check_in ahead of mam_special_offers_handler::check_in_or_out().
5. Verify
Open the mobile app on a test user account and navigate to the offer.
- The detail screen should now show an “I’m Going” check-in button.
- Tapping it should:
- Flip the button to a Cancel state and reveal a Confirmation QR code section.
- Send a Special Offers – RSVP Coming to Event notification to the venue email’s user (push, email, in-app).
- Tapping again should clear the RSVP — the QR section disappears and
mam_so_is_going_{user_id}is deleted.
If the button doesn’t appear, double-check that special-offer-has-rsvp is non-empty on the offer (get_post_meta( $offer_id, 'special-offer-has-rsvp', true )). If the button appears but no notification arrives, the email-to-user lookup is the most likely culprit.
Variations
RSVP without email notification
Skip step 3. The RSVP is still tracked in mam_so_is_going_* meta and the QR code still renders, but no notification fires. Useful for free events where attendance is a self-serve guest list.
Inspect who’s RSVPed
Per-user RSVP state is on the offer, not the user. Walk the offer’s meta to enumerate attendees:
$attendees = array();
foreach ( get_post_meta( $offer_id ) as $key => $value ) {
if ( str_starts_with( $key, 'mam_so_is_going_' ) && ! str_starts_with( $key, 'mam_so_is_going_date_' ) ) {
$user_id = (int) substr( $key, strlen( 'mam_so_is_going_' ) );
$attendees[] = $user_id;
}
}
The paired mam_so_is_going_date_{user_id} keys hold the dates each user RSVPed for, if the app sent one.
Disable RSVP later
Clear the flag:
delete_post_meta( $offer_id, 'special-offer-has-rsvp' );
The button disappears from the app immediately. Existing mam_so_is_going_* keys are not deleted — re-enabling later restores the previous guest list.
Common gotchas
- The recipient lookup is by
WP_Useremail, not the email field on the offer alone. A typo or unregistered address sends nothing, with no error. - The QR code is
wp_create_nonce( 'tsl_rental_manager_ ' . $post->ID . '_' . $user_id ). The leading space inside the action string is intentional and deployed — verifiers must use the same action string. Don’t “fix” it. - Cancellation does not unsend notifications. If a user RSVPs and immediately cancels, the venue still got the email. There’s no cancellation notification path.
- Quantity Remaining is informational only. It does not gate
mam_check_in. See step 4.
Verification
This article was last verified against:
- Plugin:
mam-special-offersv2.1 - Source:
mam-special-offers/includes/special-offers-handler.php - Source:
mam-special-offers/includes/content-class-special-offers.php(RSVP rendering inget_post_content) mam-mainnotification system
Re-verify whenever the mam_check_in action signature changes, the per-user meta key prefix (mam_so_is_going_) changes, the QR wp_create_nonce action string changes, or the special-offers-event-rsvp notification slug is renamed.
Related articles
- Plugin: mam-special-offers
- Recipe: Add a special offer to a listing
- Recipe: Let venue owners manage offers from the app
Metadata
| Field | Value |
|---|---|
| Article type | Recipe (Admin) |
| Plugin slug | mam-special-offers |
| Applies to plugin version | 2.1+ |
| Category | Building Your App |
| Audience | WordPress admin |
| Estimated time | 10 minutes |
| Prerequisites article | Recipe: Add a special offer to a listing |
| Last verified | 2026-05-01 |
