Recipe: Enable RSVP for a special offer

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-main so 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:

  1. The offer’s app detail screen renders an “I’m Going” check-in button. It dispatches the mam_check_in action on tap, with the offer’s post ID in $_REQUEST['checkinloc'].
  2. The plugin tracks per-user RSVP state in post meta. Each attending user gets a mam_so_is_going_{user_id} key set to yes, plus a paired mam_so_is_going_date_{user_id} storing the date they signed up for (sent by the app as this_date).
  3. A notification fires on RSVP. If special-offer-rsvp-email is set on the offer, a special-offers-event-rsvp notification is sent to the user matching that email — push, email, and in-app — with attendee_name available as a replacement.
  4. The offer’s detail screen gains a Confirmation section. The user’s RSVP carries a wp_create_nonce token rendered as a QR code under the Confirmation heading. Tapping the button again dispatches mam_check_in to 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_User email, 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-offers v2.1
  • Source: mam-special-offers/includes/special-offers-handler.php
  • Source: mam-special-offers/includes/content-class-special-offers.php (RSVP rendering in get_post_content)
  • mam-main notification 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.


  • 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
Contents

    Need Support?

    Can’t find the answer you’re looking for? Don’t worry we’re here to help!