# Frontend events

> Look up the callbacks, events, and window messages Bolt sends to your storefront page from Bolt Checkout, the SSO sign-in modal, and the Embedded API.

Source: https://help.boltapp.com/developers/frontend-events

Each Bolt script reports what the shopper does in its own way. Find the script your page loads:

| Your page loads                  | Bolt reports through                                                        | Section                                 |
| -------------------------------- | --------------------------------------------------------------------------- | --------------------------------------- |
| `connect.js`, for Bolt Checkout  | Callbacks you pass to `BoltCheckout.configure`, including `onNotify` events | [Bolt Checkout](#bolt-checkout)         |
| `account.js`, for SSO Commerce   | Window messages from the sign-in modal                                      | [SSO sign-in modal](#sso-sign-in-modal) |
| `embed.js`, for the Embedded API | Events on the `Bolt` object                                                 | [Embedded API](#embedded-api)           |

These run in the shopper's browser. Use them to update your page and to send analytics, not as a record of payment: confirm orders on your server with [Merchant Callbacks](/api-reference/merchant-callback/overview) and [webhooks](/developers/webhooks).

## Bolt Checkout [#bolt-checkout]

Pass callbacks in the third argument of `BoltCheckout.configure`. Every callback is optional. This example sends checkout start and every notification to a Google Tag Manager data layer:

```javascript title="JavaScript"
const callbacks = {
  onCheckoutStart() {
    window.dataLayer?.push({ event: "bolt_checkout_start" });
  },
  onNotify({ eventName, eventSeverity }) {
    window.dataLayer?.push({ event: "bolt_notify", bolt_event: eventName, bolt_severity: eventSeverity });
  },
  success(transaction, callback) {
    // Update your page, then let checkout finish.
    callback();
  },
};

// token is the order token from your backend, as in Web checkout.
BoltCheckout.configure({ orderToken: token }, {}, callbacks);
```

Where you register callbacks depends on your storefront. The plugin settings cover some callbacks, not all of them.

| Storefront               | Where callbacks go                                                                                                                                                              |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Your own storefront code | The third argument of `BoltCheckout.configure`. See [Web checkout](/platforms/direct-api).                                                                                      |
| BigCommerce              | `BoltCheckout.setClientCustomCallbacks(callbacks)`. See [BigCommerce callbacks](https://help.boltapp.com/platforms/bigcommerce/bigcommerce-setup-guide/bigcommerce-callbacks/). |
| Adobe Commerce           | The Bolt plugin's **Advanced options**, in fields such as **Tracking: onCheckoutStart**                                                                                         |
| WooCommerce              | The Bolt plugin's settings, in fields such as **Javascript event: onCheckoutStart**                                                                                             |

### Callbacks [#callbacks]

| Callback                                    | Arguments                                                                                                                                                                                            | When Bolt calls it                                                                                                                                                                                      |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `check()`                                   | None                                                                                                                                                                                                 | The shopper tries to open checkout. Return `true`, or a promise of `true`, to open it. Return `false` to keep it closed. Checkout also stays closed if a returned promise takes longer than 10 seconds. |
| `onCheckoutStart()`                         | None                                                                                                                                                                                                 | Checkout opened and shows its first step.                                                                                                                                                               |
| `onEmailEnter(email)`                       | `email`: the address                                                                                                                                                                                 | The shopper entered a valid email address or changed it, or logged in to their Bolt account.                                                                                                            |
| `onCredentialsCheck({ email, recognized })` | `email`, and `recognized`: `true` when the shopper can log in to a Bolt account with that email                                                                                                      | Bolt checked the email the shopper entered. Also called with `recognized: true` when the shopper opens checkout already logged in.                                                                      |
| `onShippingDetailsComplete(address)`        | `address`: the shipping address, with fields such as `first_name`, `last_name`, `street_address1`, `locality`, `region`, `postal_code`, `country_code`, `phone`, and `email`. Missing for Apple Pay. | The shopper completed the shipping address. Multi-step checkout only.                                                                                                                                   |
| `onShippingOptionsComplete()`               | None                                                                                                                                                                                                 | The shopper chose how the order ships. Multi-step checkout only.                                                                                                                                        |
| `onPaymentSubmit(customFields)`             | `customFields`: the shopper's custom field responses, keyed by custom field public ID                                                                                                                | The shopper selected the pay button.                                                                                                                                                                    |
| `onUpsellPageShown(cart)`                   | `cart`: the order's cart                                                                                                                                                                             | A post-purchase offer appeared. Only when your checkout shows post-purchase offers.                                                                                                                     |
| `onUpsellDecision({ cart, decision })`      | `cart`, and `decision`: `accepted`, `declined`, `timed_out`, or `abandoned`                                                                                                                          | The shopper responded to a post-purchase offer, or the offer timed out or was abandoned.                                                                                                                |
| `success(transaction, callback)`            | `transaction`: the completed transaction. `callback`: call it when your code finishes.                                                                                                               | Payment succeeded. Checkout waits up to 10 seconds for `callback()`, then continues without it.                                                                                                         |
| `close()`                                   | None                                                                                                                                                                                                 | The checkout modal closed. Not called when Bolt redirects the shopper to your `order_received_url`.                                                                                                     |
| `onNotify(notifyEvent)`                     | `notifyEvent`: see [onNotify events](#onnotify-events)                                                                                                                                               | Checkout reported one of the events below.                                                                                                                                                              |

### onNotify events [#onnotify-events]

`notifyEvent` has an `eventName`, an `eventSeverity` of `info` or `error`, and, for some events, an `eventMetadata` object. Bolt adds events over time, so ignore names you don't recognize.

```json title="Example notifyEvent"
{
  "eventName": "error_invalid_payment",
  "eventSeverity": "error",
  "eventMetadata": { "reasonCode": "payment_declined" }
}
```

#### Info events [#info-events]

| Event                             | `eventMetadata`                                                                                      | When it fires                                                                                                                                                                                                        |
| --------------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `info_account_creation_checked`   | None                                                                                                 | The shopper checked the box to create a Bolt account.                                                                                                                                                                |
| `info_account_creation_unchecked` | None                                                                                                 | The shopper cleared the box to create a Bolt account.                                                                                                                                                                |
| `info_address_added`              | None                                                                                                 | A logged-in shopper submitted a new or edited address. Also sent when the save fails.                                                                                                                                |
| `info_address_edited`             | None                                                                                                 | Checkout finished updating the order's address, including after it loads a logged-in shopper's saved addresses.                                                                                                      |
| `info_apm_selected`               | `apm`: the payment method, such as `paypal`, `applepay`, or `klarna`                                 | The shopper selected an alternative payment method, or a saved one became the selected payment.                                                                                                                      |
| `info_checkbox_checked`           | `checkbox_public_id`: the custom field's public ID                                                   | Reports a checked custom field. Sent for each custom field whenever checkout changes step, and again when payment details are complete.                                                                              |
| `info_checkbox_unchecked`         | `checkbox_public_id`                                                                                 | Reports an unchecked custom field. Sent for each custom field whenever checkout changes step.                                                                                                                        |
| `info_checkout_transition`        | `nextStep`: the step checkout moves to, such as `shipping_method`, `payment`, or `logged_in_summary` | Checkout moved to another step.                                                                                                                                                                                      |
| `info_custom_field_submitted`     | `customFieldId`: the custom field's external ID. `value`: the response.                              | A guest continued from the shipping address step to the delivery step, or a logged-in shopper started payment. Sent once for each custom field. Guests in a checkout without a separate delivery step don't send it. |
| `info_delivery_option_selected`   | `cart`, and `shippingTier`: the delivery option's name                                               | The shopper selected a delivery option.                                                                                                                                                                              |
| `info_delivery_option_submitted`  | `cart`, `shippingTier`                                                                               | The shopper continued from the delivery step to payment.                                                                                                                                                             |
| `info_discount_removed`           | `discountCode`, and `discountAmount` when checkout knows it                                          | The shopper removed a coupon or other discount. Not sent for gift cards.                                                                                                                                             |
| `info_discount_successful`        | `discountCode`, and `discountAmount` when checkout knows it                                          | A coupon or other discount applied.                                                                                                                                                                                  |
| `info_giftcard_successful`        | None                                                                                                 | A gift card applied.                                                                                                                                                                                                 |
| `info_payment_processing`         | None                                                                                                 | Checkout started authorizing the payment.                                                                                                                                                                            |
| `info_payment_type_added`         | None                                                                                                 | The shopper chose to add a new card.                                                                                                                                                                                 |
| `info_payment_type_edited`        | None                                                                                                 | The shopper deleted a saved card.                                                                                                                                                                                    |
| `info_payment_type_selected`      | None                                                                                                 | A card became the selected payment, whether the shopper chose it or checkout selected it by default.                                                                                                                 |
| `webview_link_clicked`            | `url`                                                                                                | The shopper selected a link in checkout running inside a WebView. Checkout doesn't open the link; open `url` from your app.                                                                                          |

`discountAmount` has `amount`, `currency`, and `currency_symbol`, with `amount` in the currency's minor unit, such as cents. `cart` is the cart as checkout shows it.

Bolt can turn off `info_checkout_transition`, `info_address_edited`, `info_checkbox_checked`, and `info_checkbox_unchecked` for a division. If you don't receive them, contact Bolt support.

#### Error events [#error-events]

| Event                                | `eventMetadata`                                                                                                                                                    | When it fires                                                                                                                          |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `error_discount_unsuccessful`        | None                                                                                                                                                               | A coupon or other discount didn't apply.                                                                                               |
| `error_giftcard_unsuccessful`        | None                                                                                                                                                               | A gift card didn't apply, or couldn't be removed.                                                                                      |
| `error_invalid_address`              | None                                                                                                                                                               | Checkout showed an error on a shipping address field, or the shipping address is incomplete.                                           |
| `error_invalid_email`                | None                                                                                                                                                               | Checkout showed an error on the email field.                                                                                           |
| `error_invalid_name`                 | None                                                                                                                                                               | Checkout showed an error on the shipping first or last name field.                                                                     |
| `error_invalid_payment`              | `reasonCode`: `payment_declined`, `duplicate_transaction`, `payment_method_not_supported`, or `bot_check_failed`. Missing when saved payment methods fail to load. | A payment attempt failed, or the shopper's saved payment methods didn't load. Every card or issuer decline reports `payment_declined`. |
| `error_login_unsuccessful`           | None                                                                                                                                                               | A login code couldn't be sent or verified, the shopper's email or phone failed validation, or the shopper reached a rate limit.        |
| `error_remove_discount_unsuccessful` | None                                                                                                                                                               | A discount couldn't be removed.                                                                                                        |
| `error_shipping`                     | None                                                                                                                                                               | A logged-in shopper's saved addresses, or the delivery options, didn't load.                                                           |
| `error_tax`                          | None                                                                                                                                                               | Tax couldn't be calculated.                                                                                                            |

## SSO sign-in modal [#sso-sign-in-modal]

`account.js` opens Bolt's sign-in modal for [SSO Commerce](/products/add-ons/sso-commerce). When a shopper logs in with a verification code, the modal posts window messages to your page as JSON strings. It doesn't call `onNotify` or any other callback, so listen for `message` events on `window`.

<Warning>
  These window messages are not a stable interface. Bolt can change or remove them at any time, including in ways that break code listening for them. Ignore fields you don't expect, and don't make sign-in or checkout depend on them.
</Warning>

Accept messages only from Bolt's sign-in frame: `https://connect.boltapp.com` in production and `https://connect-sandbox.boltapp.com` in sandbox. That is not the host that serves `account.js`, which redirects to `account.boltapp.com`. If your page loads `account.js` from a `bolt.com` host, the frame and its messages use `https://connect.bolt.com` or `https://connect-sandbox.bolt.com` instead.

Bolt sends these messages only to pages on your division's Trusted Domains, set in the Merchant Dashboard. A page on any other origin, such as `www.example.com` when only `example.com` is listed, receives none.

```javascript title="JavaScript"
const BOLT_ORIGIN = "https://connect.boltapp.com";

window.addEventListener("message", (event) => {
  if (event.origin !== BOLT_ORIGIN || typeof event.data !== "string") return;

  let message;
  try {
    message = JSON.parse(event.data);
  } catch {
    return;
  }
  if (message.type !== "onNotify") return;

  const { eventName, eventMetadata } = message.notifyEvent;
  if (eventName === "login_outcome") {
    window.dataLayer?.push({ event: "bolt_sso_login", outcome: eventMetadata.outcome });
  }
});
```

Each message has this shape:

```json title="Message"
{
  "type": "onNotify",
  "notifyEvent": {
    "eventName": "login_outcome",
    "eventSeverity": "info",
    "eventMetadata": { "outcome": "SUCCESS" }
  }
}
```

| Event             | `eventSeverity`                 | `eventMetadata`                                   | When it fires                                                                                                                                                                                                                                               |
| ----------------- | ------------------------------- | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `login_attempted` | `info`                          | `email`: the email the shopper entered to sign in | The shopper continued to the verification-code screen. Retrying a code on that screen sends no new event. Going back and continuing again, with the same or a different email, sends a new one.                                                             |
| `login_outcome`   | `info`, or `error` for `FAILED` | `outcome`: `SUCCESS`, `FAILED`, or `ABANDONED`    | `SUCCESS`: Bolt accepted the code, before any platform login or redirect. `FAILED`: Bolt rejected a code; each rejected retry sends one. `ABANDONED`: the shopper closed the modal without logging in, including after a rejected code or after going back. |

* One login can send several `login_attempted` and `FAILED` events, then at most one `SUCCESS` or `ABANDONED`. Nothing follows either of those.
* No outcome is sent when the shopper goes back from the code screen or leaves the page with the modal open, or for a login response that arrives after the modal closed.
* These events cover verification-code login only, not registration, social login, or dashboard login.
* `login_attempted` carries the shopper's email, and any script on your page can read window messages, so treat it as shopper data. No message carries a verification code or token.

## Embedded API [#embedded-api]

`embed.js` emits events on the `Bolt` object when shoppers log in and when Bolt checks their accounts. Call `Bolt.initialize` first: `Bolt.on` and `Bolt.once` throw an error before it.

```typescript title="Signature"
Bolt.on(eventName: string, callback: (payload: any) => void, options?: { replayLast?: boolean }): () => void;
Bolt.once(eventName: string, callback: (payload: any) => void): () => void;
```

* `Bolt.on` calls `callback` every time the event fires. `Bolt.once` calls it the next time only.
* Both return a function that removes the listener.
* With `replayLast: true`, `Bolt.on` also runs the callback right away with the event's latest payload, if the event already fired on this page. Don't pass `replayLast` to `Bolt.once`: when the event already fired, it throws an error instead of running the callback.

```javascript title="JavaScript"
Bolt.initialize("YOUR_PUBLISHABLE_KEY");

// Runs on every successful login.
const stopListening = Bolt.on("login_succeeded", ({ result }) => {
  sendAuthorizationCodeToServer(result.authorizationCode); // your function
});

// Runs once, the next time the shopper logs out.
Bolt.once("logout", () => {
  showSignedOutHeader(); // your function
});

// Later, stop listening for logins.
stopListening();
```

| Event                      | Payload                                                                         | When it fires                                                                                                                                                                                                                                                                                                                     |
| -------------------------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account_check_complete`   | `{ email, result }`: `result` is `true` when the email has a Bolt account       | Bolt finished checking an email the shopper entered.                                                                                                                                                                                                                                                                              |
| `auto_authorize_complete`  | `{ email, result }`: `result` is the login result or an `Error`                 | A login that email detection started has ended.                                                                                                                                                                                                                                                                                   |
| `forgot_password_continue` | `{ email, error }`                                                              | The shopper selected the element you attached with `context: "forgot_password"`, and Bolt didn't log them in. Continue with your own password reset. `email` is empty when no valid email was entered. When the login fails, the event fires twice, first with the email and then with an empty `email`, so start only one reset. |
| `login`                    | The shopper's email, as a string                                                | The shopper logged in, or `Bolt.helpers.checkShopper()` found an active Bolt session.                                                                                                                                                                                                                                             |
| `login_complete`           | `{ email, result, loginContext }`: `result` is the login result or an `Error`   | A login attempt ended, whether it succeeded or failed.                                                                                                                                                                                                                                                                            |
| `login_failed`             | `{ email, result, loginContext }`: `result` is an `Error`                       | A login attempt failed.                                                                                                                                                                                                                                                                                                           |
| `login_modal_closed`       | `{ context }`                                                                   | The login modal closed after a login attempt, for any reason.                                                                                                                                                                                                                                                                     |
| `login_modal_dismissed`    | `{ context }`                                                                   | The shopper closed the login modal without logging in.                                                                                                                                                                                                                                                                            |
| `login_succeeded`          | `{ email, result, loginContext }`: `result` has `authorizationCode` and `scope` | A login attempt succeeded. Exchange `authorizationCode` on your server with [Bolt OAuth](https://help.boltapp.com/developers/bolt-oauth/).                                                                                                                                                                                        |
| `logout`                   | `{}`                                                                            | `Bolt.helpers.logout()` logged the shopper out.                                                                                                                                                                                                                                                                                   |
| `mount_failed`             | `{ component, email, context, reason }`                                         | `mountPasswordlessLoginButton()` couldn't show the login button. `component` is `login_button`. `reason` is `Invalid email`, `No account found` in the `checkout` context, or an error message.                                                                                                                                   |

`context` and `loginContext` are the context you gave the login modal: `checkout`, `sign_in`, `register`, `pre_checkout`, or `forgot_password`.

### Events kept for older integrations [#events-kept-for-older-integrations]

These still fire. Use the newer event in new code.

| Event                         | Payload                                                  | Use instead                                                                                               |
| ----------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `authorize_complete`          | `{ email, result }`                                      | `login_complete`. Fires with every `login_complete`, and when the older authorization component finishes. |
| `auto_account_check_complete` | `{ email, result }`: `result` is a boolean or an `Error` | `account_check_complete`. This event is deprecated.                                                       |
| `authorize_modal_closed`      | `{ context: "checkout" }`                                | `login_modal_closed`. Sent only by the older authorization component.                                     |

Components report their own events through the component's `on` method, such as the payment fields' `error` event and the account checkbox's `change` event. See [Payment fields](https://help.boltapp.com/products/checkout/embeddable-checkout/api-implementation/components/payment-fields/) and [Account checkbox](https://help.boltapp.com/products/checkout/embeddable-checkout/api-implementation/components/account-checkbox/).
