Step callbacks
onStepShown, onStepSuccess, and onStepError report progress inside a component as the user moves through it, at the level of individual steps rather than the flow as a whole. They are shared across the LoginRadius JavaScript SDK and LoginRadius React SDK, with identical option names and payload shapes in both. Add them alongside the existing onSuccess and onError options on any flow orchestrator or bundled component to drive analytics, custom progress indicators, and step-level error monitoring without inspecting the DOM or parsing message text.
When to use these callbacks
onSuccess and onError report only the outcome of the whole component — a completed login, a failed profile update. They say nothing about which screen the user was on or which of several actions inside that screen ran. onStepShown, onStepSuccess, and onStepError fill that gap:
- Send step-by-step funnel analytics for a login or registration flow — which step users reach, and where they drop off.
- Drive a custom progress indicator across a multi-step flow instead of relying on which component is currently mounted.
- Log or alert on step-level failures, for example a repeatedly failing MFA step, without parsing the text of a displayed error message.
- Detect a successful action, such as a resend OTP click, that intentionally shows no user-facing message in
messageType: 'none'mode.
If you only need to know whether the overall flow ultimately succeeded or failed, onSuccess and onError remain the simpler choice.
Configure the callbacks
All three options are optional and accepted alongside onSuccess and onError. If you deploy through LoginRadius Hosted Pages (Auth Studio), set them on the commonoptions object in your template's Before Script instead of in your own application code.
JavaScript SDK
React SDK
Auth Studio – Before Script
LRObject.init("auth", {
container: "auth-container",
onSuccess: (res) => console.info("Login complete", res),
onError: (err) => console.error("Login failed", err),
onStepShown: (info) => console.info("Step shown", info),
onStepSuccess: (info) => console.info("Step success", info),
onStepError: (info) => console.error("Step error", info),
});
import { Auth } from "@loginradius/loginradius-react";
<Auth
onSuccess={(response) => console.info("Login complete", response)}
onError={(error) => console.error("Login failed", error)}
onStepShown={(info) => console.info("Step shown", info)}
onStepSuccess={(info) => console.info("Step success", info)}
onStepError={(info) => console.error("Step error", info)}
/>;
// Auth Studio → template editor → Pages → Auth → Before Script.
// Set the options on `commonoptions` before the SDK is created.
commonoptions.onStepShown = function (info) {
console.info("Step shown", info);
};
commonoptions.onStepSuccess = function (info) {
console.info("Step success", info);
};
commonoptions.onStepError = function (info) {
console.error("Step error", info);
};
// Already present in the default Before Script:
var LRObject = new LoginRadiusSDK(commonoptions);
Payload reference
The tables below describe the payload each callback receives. All three are supported by both SDKs with the same field names and types.
onStepShown
Fires once for each distinct step, the moment that step has finished loading and is interactive, not on mount, and not again on a re-render of the same step.
| Property | Type | Description |
|---|---|---|
step | string | Identifier of the step now shown. See Flow and step identifiers. |
flow | string | The flow this step belongs to — auth, login, register, passwordless, forgotPassword, social, verification, profile, or adminPortal. |
previousStep | string | undefined | The step the user was on immediately before, when known. undefined on the first step of a flow. |
onStepSuccess
Fires whenever the API call backing a step's action succeeds. This includes the step's primary action (submitting a login form, verifying an OTP) and any secondary action within the same step that also calls the API, such as a resend link or a secondary sign-in method.
| Property | Type | Description |
|---|---|---|
step | string | Identifier of the step or action that succeeded. |
data | unknown | The API response for the call that succeeded. Shape depends on the endpoint. |
isFinal | boolean | true when this success ends the flow (for example, a completed login). false when the flow continues to another step, or the action was a same-step side effect such as a resend. |
onStepError
Fires whenever the API call backing a step's action fails, or a client-side validation check blocks the action before any API call is made.
| Property | Type | Description |
|---|---|---|
step | string | Identifier of the step or action that failed. |
error | unknown | The error returned by the API, or a { error: string } object for client-side validation failures. |
routedTo | string | undefined | The step the SDK routed to as a result of this error, when the error changes the current step (for example, an account-locked error routing to a dedicated error screen). undefined when the error is shown in place. |
onStepSuccess reports whether the underlying API call succeeded, independent of whether a message is shown to the user. A resend action still fires onStepSuccess in messageType: 'none' mode, where no visible confirmation appears.
Resend actions and step success
A step's primary action and any resend or secondary action on that same screen report the same step identifier, since they represent the same logical step to the user. The payload does not label which one occurred, both report isFinal: false when the flow continues. Distinguish them in your own handler by tracking which action you triggered, if your analytics require that level of detail.
For screens where a secondary action switches to a materially different sign-in method, passkey authentication from the login screen, for example, step reports the action taken (passkey_login) rather than the screen it was triggered from (login), so a funnel built on onStepSuccess distinguishes password sign-in from passkey sign-in even though both start on the same screen.
Flow and step identifiers
Each flow's step values come from its own set of screens. The tables below cover the identifiers you will see for each flow value.
auth, login, passwordless, register, verification, forgotPassword
These flows share one underlying step registry, so the same identifiers appear across them wherever the corresponding screen is reachable in that flow.
step | Screen |
|---|---|
login | Sign-in form |
register | Sign-up form |
auto_lookup | Identifier lookup (email or phone) before sign-in |
identifier_availability | Identifier availability check before sign-up |
required_fields / optional_fields | Additional-profile-fields collection |
mfa_selector | MFA method selection |
sms_otp / email_otp / totp / push_notification / duo_security | MFA verification, per method |
verify_sms_otp / verify_email_otp / verify_email_link | Post-registration identifier verification |
passwordless_login_email / passwordless_login_sms | Passwordless sign-in request |
verify_passwordless_login_email / verify_passwordless_login_email_otp / verify_passwordless_login_sms | Passwordless sign-in confirmation |
passkey_login / passkey_registration | Passkey sign-in and passkey enrollment |
set_login_pin / login_by_pin / forgot_pin / pin_magic_link | PIN sign-in setup, entry, and recovery |
reset_password_by_otp / reset_password_by_phone_otp / reset_pin_by_otp | Password and PIN reset |
backup_codes | MFA backup code display |
consent_form / privacy_policy | Consent and privacy policy acceptance |
social
step | Screen |
|---|---|
social | Social provider selection (entry screen) |
consent_form / privacy_policy | Consent and privacy policy acceptance following a social sign-in |
set_login_pin | PIN sign-in setup, when required after a social sign-in |
profile
One step per section of the Profile component and its individually-rendered sub-components:
profileDetails, email, phone, social, username, password, pin, mfa, consent, passkey, backupCodes, deleteAccount
Profile renders several of these sections at once inside a tab, so switching tabs produces onStepShown for every section on that tab together rather than one at a time, each section is genuinely visible on screen at the same moment.
adminPortal
AdminPortal reuses the profile step identifiers above for its Account and Security tabs, plus these for its B2B organization tabs:
organizationSettings, organizationDomainManagement, organizationDangerZone, userManagement, roles, organizationSecurity, connections, scim
Supported components
onStepShown, onStepSuccess, and onStepError are supported on:
- Every flow orchestrator,
Auth,Login,Register,SocialLogin,PasswordlessLogin,ForgotPassword,VerificationToken, and the individual step components they render, when rendered on their own. Profileand every individually-exported profile sub-component (PersonalDetails,AddEmail,ChangePassword,SetupTwoFactorAuth,AddPasskey, and the rest of the account management components in the JavaScript SDK and React SDK).AdminPortaland its B2B organization sub-components, documented under Common props in the React SDK components reference.
They are not available on OrganizationSwitcher, OrganizationSelector, or Workflow, these components do not report step-level progress.
Handle errors in your own callback
An exception thrown inside your onStepShown, onStepSuccess, or onStepError implementation is caught internally and logged to the console. It never interrupts the SDK's own flow logic, a bug in your analytics call cannot block a step transition or leave the SDK in an inconsistent state.
Advanced example
The following tracks a login funnel and drives a custom step indicator, while keeping the built-in onSuccess and onError handlers for the final outcome.
JavaScript SDK
React SDK
Auth Studio – Before Script
let currentStep = null;
const indicator = document.getElementById("step-indicator");
function handleStepShown(info) {
currentStep = info.step;
indicator.textContent = `Step: ${currentStep}`;
console.info("Step shown", info);
}
function handleStepSuccess(info) {
console.info("Step success", info);
}
function handleStepError(info) {
console.error("Step error", info);
}
LRObject.init("auth", {
container: "auth-container",
onSuccess: (res) => console.info("Signed in", res),
onError: (err) => console.error("Sign-in failed", err),
onStepShown: handleStepShown,
onStepSuccess: handleStepSuccess,
onStepError: handleStepError,
});
import { useState } from "react";
import { Auth } from "@loginradius/loginradius-react";
import type {
StepShownInfo,
StepSuccessInfo,
StepErrorInfo,
} from "@loginradius/loginradius-core";
const LoginPage = () => {
const [currentStep, setCurrentStep] = useState<string | null>(null);
const handleStepShown = (info: StepShownInfo) => {
setCurrentStep(info.step);
console.info("Step shown", info);
};
const handleStepSuccess = (info: StepSuccessInfo) => {
console.info("Step success", info);
};
const handleStepError = (info: StepErrorInfo) => {
console.error("Step error", info);
};
return (
<div>
{currentStep && <p className="step-indicator">Step: {currentStep}</p>}
<Auth
onSuccess={(response) => console.info("Signed in", response)}
onError={(error) => console.error("Sign-in failed", error)}
onStepShown={handleStepShown}
onStepSuccess={handleStepSuccess}
onStepError={handleStepError}
/>
</div>
);
};
export default LoginPage;
// Hosted pages render server-side and have no framework state,
// so drive the indicator straight from the DOM.
commonoptions.onStepShown = function (info) {
var indicator = document.getElementById("step-indicator");
if (indicator) indicator.textContent = "Step: " + info.step;
console.info("Step shown", info);
};
commonoptions.onStepSuccess = function (info) {
console.info("Step success", info);
};
commonoptions.onStepError = function (info) {
console.error("Step error", info);
};
var LRObject = new LoginRadiusSDK(commonoptions);
Related resources
- Options reference —
messageTypeand other options that control what the user sees while these callbacks fire in the background. - JavaScript SDK components — full component reference, including the
onSuccess/onErroroptions these callbacks extend. - React SDK components — full component reference, including the
onSuccess/onErrorcommon props these callbacks extend. - useLRAuth() reference — read authentication state directly instead of, or alongside, step callbacks (React SDK only).
- Auth Studio pages — how the Before Script creates the SDK instance that
commonoptionsconfigures.