Use the ETA Buy Button to sell M Ride tickets on your website

Overview

The ETA Buy Button is a JavaScript widget that embeds a shuttle ticket purchasing flow into any webpage. Configuration is split across two places:

  • The <script> tag — global settings that apply to the entire widget instance (API endpoint, styling, callbacks)
  • Each <button> tag — per-event settings that control what happens when a specific button is clicked

1. Install the Script Tag

Add the following <script> tag near the bottom of your <body>. The id must be exactly eta-buy-button.

<script id="eta-buy-button"
        src="https://widget.mride.com/static/js/widget.js"
        type="module"
        data-trigger-class="shuttle-btn"
        data-api-url="https://widget.mride.com/api/v1">
</script>

Script Tag Attributes

Attribute Required Default Description
id Yes Must be eta-buy-button. The widget will throw an error if this is missing.
src Yes URL to the widget JavaScript file.
type Yes Must be module.
data-trigger-class No shuttle-btn The CSS class the widget listens for click events on. Any button with this class will open the widget.
data-root-element No shuttle-widget The id given to the widget's root DOM element. Must be unique on the page.
data-api-url No https://widget.mride.com/api/v1 Base URL for the ETA API.
data-stylesheet No Hosted CDN URL URL to the widget's main CSS file.
data-fonts No Hosted CDN URL URL to the widget's fonts CSS file.
data-brand No Hosted CDN URL URL to a brand/theme CSS file for visual customization.
data-program No mride Default partner program applied to all buttons. Can be overridden per button.
data-strip-return-params No false When true, strips query parameters from the return URL after Stripe checkout completes.
data-on-error No Name of a global JavaScript function to call when an unhandled error occurs. See Error Handling.
data-on-order-begin No Name of a global JavaScript function to call when a customer begins an order.
data-on-order-complete No Name of a global JavaScript function to call when an order is completed.

2. Add Event Buttons

Place one or more buttons anywhere in your page. Each button must have the CSS class that matches data-trigger-class on the script tag (default: shuttle-btn).

<button class="shuttle-btn" data-event-id="your-event-id">
    Book Now
</button>

Button Attributes

Attribute Required Description
data-event-id Yes The event identifier to load when this button is clicked.
data-promo-code No A promo/discount code to apply automatically when the widget opens.
data-program No Partner program for this button. Overrides the script-level data-program value.

3. Examples

Single event, no customization

<button class="shuttle-btn" data-event-id="my-event">Book Now</button>

<script id="eta-buy-button"
        src="https://widget.mride.com/static/js/widget.js"
        type="module"
        data-api-url="https://widget.mride.com/api/v1">
</script>

Multiple events on the same page

All buttons sharing data-trigger-class are handled by a single widget instance.

<button class="shuttle-btn" data-event-id="ed-sheeran-sf-26">Book Ed Sheeran Shuttle</button>
<button class="shuttle-btn" data-event-id="foo-fighters-lv-26">Book Foo Fighters Shuttle</button>

<script id="eta-buy-button"
        src="https://widget.mride.com/static/js/widget.js"
        type="module"
        data-api-url="https://widget.mride.com/api/v1">
</script>

Pre-apply a promo code

The widget will automatically apply the discount when the modal opens.

<button class="shuttle-btn"
        data-event-id="summer-festival"
        data-promo-code="SUMMER20">
    Book with Discount
</button>

Partner program

M Ride can create a program for your organization. A program enables the following capabilities, configured by M Ride on your behalf:

  • Custom branded confirmation emails — full branding and content, sent from your email address, with optional BCC recipients
  • Automatic discounts — pre-applied discount rates reflecting agreed-upon partner pricing, with no promo code required from the customer
  • Filtered pickup locations — only the pickup locations relevant to your program are shown in the widget; all others are excluded from every API response

Contact your M Ride representative to have a program created. Once set up, you reference it by its program identifier in your button or script tag configuration.

Override the default program on a per-button basis.

<!-- Uses the default program from the script tag -->
<button class="shuttle-btn" data-event-id="my-event">Book Now</button>

<!-- Uses a specific partner program for this button -->
<button class="shuttle-btn"
        data-event-id="edc-lv-26"
        data-program="hotel-partner-name">
    Book (Hotel Guests)
</button>

To apply a partner program globally to all buttons, set it on the script tag instead:

<script id="eta-buy-button"
        src="https://widget.mride.com/static/js/widget.js"
        type="module"
        data-program="hotel-partner-name"
        data-api-url="https://widget.mride.com/api/v1">
</script>

Custom stylesheet / branding

<script id="eta-buy-button"
        src="https://widget.mride.com/static/js/widget.js"
        type="module"
        data-stylesheet="https://yoursite.com/css/widget.css"
        data-fonts="https://yoursite.com/css/fonts.css"
        data-brand="https://yoursite.com/css/brand.css"
        data-api-url="https://widget.mride.com/api/v1">
</script>

4. URL-Based Promo Codes

In addition to the data-promo-code button attribute, the widget also reads promo codes from the page URL. If the URL contains a ?promo=CODE query parameter, it is automatically applied when any button is clicked. The URL parameter takes precedence over the button attribute.


5. Error Handling

Set data-on-error to the name of a global function. The function receives an object with the eventId that triggered the error. Return true to suppress the widget's default error message.

<script id="eta-buy-button"
        src="https://widget.mride.com/static/js/widget.js"
        type="module"
        data-on-error="handleWidgetError"
        data-api-url="https://widget.mride.com/api/v1">
</script>

<script>
    function handleWidgetError(error) {
        console.error("Widget error for event:", error.eventId);
        // Return true to suppress the default "Something went wrong" message
        return true;
    }
</script>

HTTP error codes the widget handles automatically:

Status Message shown
404 "We could not find this event"
410 "Sales have ended for this event"
Other "Something went wrong" (calls data-on-error if set)

6. Security & Compliance

Domain Whitelisting

The M Ride API enforces CORS (Cross-Origin Resource Sharing), which means the widget will only function on domains that have been explicitly authorized. Before going live, contact your M Ride representative to have your domain added to the allowlist. Requests from non-whitelisted domains will be blocked by the browser before they reach the API.

Payment Data & PCI Compliance

The widget itself does not collect, handle, or store any payment card data. All payment information is entered directly into and processed by Stripe, a PCI-DSS Level 1 certified payment processor. Card numbers, expiry dates, and CVVs never pass through your website or M Ride's servers. This architecture keeps your site out of PCI scope for cardholder data.

Customer Data Collection

The widget does not collect customer personal data (name, email, phone, etc.) at any point during the booking flow. Customer information is collected by Stripe during checkout.

After a payment clears, Stripe notifies the M Ride API via a signed webhook. The following data is then received and stored by M Ride's servers:

  • First name, last name
  • Email address
  • Phone number
  • Order line items (shuttles, dates, quantities)

No customer data is transmitted through the JavaScript widget or your web page.

Webhook Security

The Stripe webhook sent to the M Ride API is cryptographically signed by Stripe. M Ride's API verifies this signature on every webhook delivery, ensuring that order data cannot be fabricated or tampered with by a third party.

What Your Site Is Responsible For

Concern Handled by
Payment card data security Stripe (PCI-DSS Level 1)
Webhook integrity Stripe signature + M Ride API
Customer PII storage M Ride API (post-payment only)
Widget JS & CSS delivery M Ride CDN (or your own hosting)
Domain authorization M Ride (contact your representative)
Your page's own security (HTTPS, CSP, etc.) You

Ensure your page is served over HTTPS. Loading the widget on an unencrypted HTTP page will cause browsers to block the Stripe checkout iframe.


7. Testing

M Ride provides a test environment that runs against Stripe's test mode. Orders placed in test mode do not consume production inventory and no real charges are made.

Enabling Test Mode

Set data-api-url to the test API endpoint:

<script id="eta-buy-button"
        src="https://widget.mride.com/static/js/widget.js"
        type="module"
        data-api-url="https://widget-test.mride.com/api/v1">
</script>
Environment data-api-url
Production https://widget.mride.com/api/v1
Test https://widget-test.mride.com/api/v1

The widget script src is the same for both environments.

Note: Your domain must be whitelisted in the test environment separately from production. Contact your M Ride representative to have it added.

Test Credit Card Numbers

Use these Stripe-provided card numbers at checkout. Enter any future expiry date (e.g. 12/34), any 3-digit CVC, and any billing ZIP code.

Card number Brand Behavior
4242 4242 4242 4242 Visa Payment succeeds
5555 5555 5555 4444 Mastercard Payment succeeds
4000 0025 0000 3155 Visa Requires 3D Secure authentication
4000 0000 0000 9995 Visa Declined — insufficient funds
4000 0000 0000 0002 Visa Declined — generic decline

A successful test order will complete the full flow: payment confirmation, webhook delivery, and the download screen with QR codes.


8. Notes

  • Only one widget instance is created per page, regardless of how many buttons are present.
  • The widget renders inside a Shadow DOM, so your page's existing CSS will not interfere with its styles.
  • The widget automatically positions itself above all other elements on the page by computing the highest z-index at load time.