@vygor/browser-sdk
v1.0.13
Published
- [Getting Started](#getting-started) - [Installation](#installation) - [Basic Usage](#basic-usage) - [Initialization](#initialization) - [Mounting Elements](#mounting-elements) - [Fetching Data](#fetching-data) - [Authentication](#authe
Readme
Vygor Browser SDK
Table of Contents
Getting Started
Installation
npm i @vygor/browser-sdkor
yarn add @vygor/browser-sdkor
pnpm i @vygor/browser-sdkBasic Usage
Initialization
Initialization must run before calling any Vygor methods or referencing properties.
Vygor.init("<your org id>");
// e.g.
Vygor.init("o_example");
// Sandbox
Vygor.init("o_example", { endpoint: "https://staging.vygorai.com" });Mounting Elements
Vygor Elements are a set of prebuilt UI components that help you quickly integrate Vygor functionality into your studio website. They handle complex workflows like checkouts and authentication.
Elements are designed to be simple to use while providing a seamless experience for your customers. They automatically handle:
- Unified authentication with Vygor and other studios powered by Vygor
- Secure payment processing
- Form validation and error handling
- Responsive layouts that work on all devices
- Consistent styling that matches your brand
- State management and data synchronization
See Vygor Elements for more info
Vygor.Element.create("googleSignIn", {}).mount(element);
// With options
Vygor.Element.create("bookingCheckout", {
bookableId: "bo_example",
membershipPlanId: "mp_example", // Optional
onSuccess(data) {
// ...
},
}).mount(element);Fetching Data
The Vygor Browser SDK makes it easy to fetch data from your Vygor organization. The SDK provides simple methods to access schedules, customer data, bookables, membership plans, and more.
Vygor.fetchSchedule().then((data) => {
/* ... */
});Authentication
Vygor has multiple customer authentication methods, we recommend using the googleSignIn element as the primary option and while allowing traditional email/password login as a fallback. The same set of options will always be available in checkout elements.
// Mount googleSignIn element
Vygor.Element.create("googleSignIn", {}).mount(element);
// Traditional login
Vygor.login(email, password);Since there are several potential login entrypoints, we recommend you use events to manage this state to instead of handling each source individually.
Vygor.on("login", ({ customer, memberships, membershipPlans }) => {
// ...
});
Vygor.on("logout", () => {
// ...
});NOTE: memberships and membershipPlans are not populated with all memberships a customer has, just memberships referenced in the customer payload.
Vygor Elements
googleSignIn
Vygor.Element.create("googleSignIn", {}).mount(element);The googleSignIn element renders a Google Sign In button that uses the OpenID Connect flow (opens a popup window instead of redirecting).
Emits login event with authenticated customer data on successful sign-in.
bookingCheckout
The bookingCheckout element renders a checkout form for booking a service. It provides a complete checkout experience including:
- Account information collection
- Guest booking management
- Optional membership purchase
- Cart and pricing resolution
- Alternative currency support (credits/guest passes)
- Secure payment processing
- Digital waiver signatures
Unauthenticated customers can log in or create an account during the checkout process. Logged-in customers will have their information pre-filled. Customers are required to have an account to make a purchase.
Emits login event with authenticated customer data when customer logs in.
Emits logout event when customer clicks log out button.
Example:
Vygor.Element.create("bookingCheckout", {
bookableId,
membershipPlanId, // Optional
onSuccess(data) {
// ...
},
}).mount(element);Options
bookableId
bookableId: Bookable.Id;The ID of the bookable to check out.
This can be obtained from the organization's schedule (Vygor.fetchSchedule())
membershipPlanId (optional)
membershipPlanId?: Membership.Plan.Id;The ID of the membership plan to purchase during checkout.
If provided, the checkout will include the membership purchase in the total. The membership will be activated immediately after successful payment.
This can be obtained from the organization's membership plans (Vygor.fetchMembershipPlans())
cart
cart?: {
hideOriginalPrice?: boolean
}Configuration options for the cart display and behavior during checkout.
Properties:
hideOriginalPrice(optional): By default, when booking with an alternative resource (membership, credits, guest passes), the original price of the bookable is displayed in the cart with a strikethrough. Enable this option to hide it.- Default:
false
- Default:
Example:
Vygor.Element.create("bookingCheckout", {
bookableId: "bo_example",
cart: {
hideOriginalPrice: true, // Only show final cost, hide original price
},
onSuccess(data) {
// ...
},
}).mount(element);onSuccess
onSuccess(data: {
customer: Customer
booking: Booking;
guestBookings: Booking[];
membership?: Membership;
}): void;Callback function that runs when the checkout completes successfully.
The callback receives an object containing:
customer: The updated current customer post checkout.booking: The created booking for the logged-in customerguestBookings: Array of bookings created for any guests added during checkoutmembership: The created membership if a membership plan was purchased during checkout, otherwise undefined
membershipCheckout
The membershipCheckout element renders a checkout form for purchasing a membership plan. This checkout experience includes:
- Account information collection
- Membership details and benefits display
- Pricing information
- Secure payment processing
- Digital agreement signing
Unauthenticated customers can log in or create an account during the checkout process. Logged-in customers will have their information pre-filled. Customers are required to have an account to make a purchase.
Emits login event with authenticated customer data when customer logs in.
Emits logout event when customer clicks log out button.
Example:
Vygor.Element.create("membershipCheckout", {
planId,
onSuccess(data) {
// ...
},
}).mount(element);Options
planId
planId: Membership.Plan.Id;The ID of the membership plan to purchase.
This can be obtained from the organization's membership plans (Vygor.fetchMembershipPlans())
onSuccess
onSuccess(data: { membership: Membership }): void;Callback function that runs when the checkout completes successfully.
The callback receives an object containing:
customer: The updated current customer post checkout.membership: The created membership that was purchased during checkout
Methods
init
Vygor.init(organizationId: Organization.Id, options?: {
endpoint?: string;
theme?: Vygor.ThemeOptions;
})Initializes the Vygor client with your organization ID. This must be called before using any other methods.
Parameters
organizationId: Your organization ID (e.g., "o_example")options.endpoint(optional): Override the default API endpoint (e.g., "https://staging.vygorai.com")options.theme(optional): Customization options for Vygor Elements. See Theming for details.
fetchSchedule
Vygor.fetchSchedule(params?: {
bookableTemplateId?: Bookable.Template.Id;
staffId?: Staff.Id;
endAtAfter?: Date;
cursor?: string;
}): Promise<Organization.Schedule & { nextCursor: string }>Fetches the organization's schedule data. You can filter the results by bookable template, staff member, or date range, and paginate through large result sets. Each page contains 50 results.
Parameters
params.bookableTemplateId(optional): Filter to show only bookables of a specific templateparams.staffId(optional): Filter to show only bookables with a specific staff memberparams.endAtAfter(optional): Filter to show only bookables ending on or after the specified dateparams.cursor(optional): Pagination cursor from a previous request's response
Returns
A promise that resolves to the organization's schedule with a pagination cursor (nextCursor) to get the next page of 50 results.
Pagination Example
const firstPage = await Vygor.fetchSchedule({
endAtAfter: new Date(), // Only show future bookables
});
// ...
const secondPage = await Vygor.fetchSchedule({
cursor: firstPage.nextCursor,
});fetchBookable
Vygor.fetchBookable(bookableId: Bookable.Id): Promise<{
bookable: Bookable;
bookableTemplate: Bookable.Template;
staff: Staff;
classTags: Bookable.Tag[];
}>Fetches a single bookable by its ID. This is useful for when a bookable is not available from the schedule endpoint (such as when it's unlisted).
Parameters
bookableId: The ID of the bookable to fetch (e.g."bo_example")
Returns
A promise that resolves to an object containing the bookable and its dependencies.
fetchOrganization
Vygor.fetchOrganization(): Promise<Organization>Fetches the current organization's details from organizationId.
Returns
A promise that resolves to an object containing the current organization.
fetchMembershipPlans
Vygor.fetchMembershipPlans(): Promise<{ membershipPlans: Membership.Plan[] }>Fetches all available membership plans for the organization.
Returns
A promise that resolves to an object containing an array of membership plans.
captureEmail
Vygor.captureEmail(email: string): Promise<{}>Captures a potential customer's email address for marketing or lead generation. These will be targetable in campaigns in your organization's Vygor admin dashboard.
Parameters
email: The email address to capture
Returns
A promise that resolves when the operation completes.
createAccount
Vygor.createAccount(email: string, password: string): Promise<{
customer: Customer;
}>Creates a new customer account.
Parameters
email: Email address for the new accountpassword: Password for the new account
Returns
A promise that resolves with an object containing the newly created customer.
Events
Emits the login event on successful account creation.
login
Vygor.login(email: string, password: string): Promise<{
customer: Customer;
memberships: Membership[];
membershipPlans: Membership.Plan[];
}>Authenticates a customer using email and password. Includes the customer's memberships.
Parameters
Returns
A promise that resolves with an object containing:
customer: The authenticated customer datamemberships: Array of the customer's membershipsmembershipPlans: Array of membership plans associated with the customer's memberships
Events
Emits the login event on successful authentication.
logout
Vygor.logout(): Promise<void>Logs out the currently authenticated customer.
Returns
A promise that resolves when the logout is complete.
Events
Emits the logout event when logout is complete.
fetchCustomer
Vygor.fetchCustomer(): Promise<{
customer: Customer;
memberships: Membership[];
membershipPlans: Membership.Plan[];
}>Fetches the currently authenticated customer's data.
Returns
A promise that resolves with an object containing:
customer: The current customer datamemberships: Array of the customer's membershipsmembershipPlans: Array of membership plans associated with the customer's memberships
on
Vygor.on(event: 'login', handler: (data: {
customer: Customer;
memberships: Membership[];
membershipPlans: Membership.Plan[];
}) => void): { off: () => void }
Vygor.on(event: 'logout', handler: () => void): { off: () => void }Registers an event handler for Vygor events.
Parameters
event: The event to listen for ('login' or 'logout')handler: The function to call when the event occurs
Returns
An object with an off method that can be called to remove the event handler.
cleanup
Vygor.cleanup(): voidCleans up all resources used by the Vygor client. Call this method when you're done using the SDK to free up memory.
Element.create
Vygor.Element.create(elementKey: Element.Key, options: Element.Options<Key>): ElementCreates a Vygor Element that can be mounted in the DOM.
Parameters
elementKey: The type of element to create ('googleSignIn', 'bookingCheckout', or 'membershipCheckout')options: Configuration options specific to the element type
Returns
An Element object with a mount method that accepts an HTML element to mount into.
The mount method returns a handle to the mounted element with a cleanup function to remove the element and free resources.
Example
const element = Vygor.Element.create("googleSignIn", {});
const { cleanup } = element.mount(document.getElementById("container"));
// Later when done with the element:
cleanup();Properties
organizationId
The organization ID the current client was initialized with.
endpoint
The endpoint the current client was initialized with.
debug
Vygor.debug = true;When set to true, enables debug logging to the console for SDK operations. This can be helpful for troubleshooting SDK interactions.
Default: false
defaultEndpoint
Vygor.defaultEndpoint = "https://staging.vygorai.com";Sets the default API endpoint for all Vygor clients. This can be used to globally configure the SDK to use a sandbox environment.
Default: "https://vygorai.com"
Models
The Vygor Browser SDK uses several data models to represent entities in your organization. Below are the core models referenced throughout the SDK.
Organization
The organization represents your studio in the Vygor system.
type Organization = {
id: Organization.Id; // e.g. "o_example"
name: string;
imgUrl: string;
email: string;
phoneNumber?: string;
websiteUrl?: string;
address: Address;
descriptionMd?: string;
};
namespace Organization {
export type Id = `o_${string}`;
}Organization.Schedule
Represents the organization's schedule, including bookable services and their availability.
namespace Organization {
export type Schedule = {
bookables: Bookable[];
recurrences: Recurrence[];
staffs: Staff[];
bookableTemplates: Bookable.Template[];
};
}Customer
Represents a customer in your organization.
type Customer = {
id: Customer.Id; // e.g. "cu_example"
email: string;
name?: {
first: string;
middle?: string;
last: string;
};
pfpUrl?: string;
phone?: string;
classVoucherWallet: Customer.ClassVoucherWallet;
guestPassWallet: Customer.GuestPassWallet;
createdAt: Date;
organizationId: Organization.Id;
};
namespace Customer {
export type Id = `cu_${string}`;
export type ClassVoucherWallet = {
id: ClassVoucherWallet.Id; // e.g. "cvw_example"
count: number;
unlimitedMembershipId?: Membership.Id;
};
export type GuestPassWallet = {
id: GuestPassWallet.Id; // e.g. "gpw_example"
count: number;
unlimitedMembershipId?: Membership.Id;
};
}Bookable
Represents a service that can be booked, e.g. "Morning Yoga Class"
type Bookable = {
id: Bookable.Id; // e.g. "bo_example"
organizationId: Organization.Id;
templateId: Bookable.Template.Id;
recurrenceId?: Recurrence.Id;
startAt: Date;
endAt: Date;
capacity?: number;
availability?: number;
staffId?: Staff.Id;
unlisted: boolean;
currentCustomerBooking?: Booking;
};
namespace Bookable {
export type Id = `bo_${string}`;
}Bookable.Template
Represents a template for bookable services with shared properties.
namespace Bookable {
export type Template = {
id: Template.Id; // e.g. "bt_example"
name: string;
description?: string;
imgUrl: string;
priceCents: number;
};
export namespace Template {
export type Id = `bt_${string}`;
}
}Booking
Represents a customer booking for a bookable.
type Booking = {
id: Booking.Id; // e.g. "bg_example"
bookableId: Bookable.Id;
customerId: Customer.Id;
status: "confirmed" | "cancelled";
resourceId: Booking.Resource.Id;
checkedInAt: Date;
};
namespace Booking {
export type Id = `bg_${string}`;
export type Resource =
| Membership
| PaymentMethod
| Customer.ClassVoucherWallet
| Customer.GuestPassWallet;
}Booking.Resource
Represents the resource used to make a booking. This can be a membership, payment method, class voucher wallet, or guest pass wallet.
Recurrence
Represents a recurring schedule for bookable services.
For rrule, see: iCalendar Recurrence Rule (RFC 5545)
Example rrule values:
FREQ=WEEKLY;BYDAY=MO,WE,FR- Every Monday, Wednesday, and FridayFREQ=WEEKLY;INTERVAL=2;BYDAY=TU- Every other TuesdayFREQ=MONTHLY;BYMONTHDAY=15- 15th day of every month
type Recurrence = {
id: Recurrence.Id; // e.g. "r_example"
rrule: string; // iCalendar Recurrence Rule (RFC 5545)
duration: number; // Duration in minutes
startAt: Date;
capacity?: number;
availability?: number;
staffId?: Staff.Id;
organizationId: Organization.Id;
templateId: Bookable.Template.Id;
};
namespace Recurrence {
export type Id = `r_${string}`;
}Staff
Represents staff members in your organization who can teach classes or provide services.
type Staff = {
id: Staff.Id; // e.g. "sp_example"
email: string;
name: {
first: string;
middle?: string;
last: string;
};
pfpUrl?: string;
phone?: string;
role: Staff.Role;
};
namespace Staff {
export type Id = `sp_${string}`;
export type Role = "staff" | "owner" | "retired";
}Membership
Represents a customer's membership.
type Membership = {
id: Membership.Id; // e.g. "m_example"
expiresAt: Date;
activatedAt: Date;
planId: Membership.Plan.Id;
customerId: Customer.Id;
};
namespace Membership {
export type Id = `m_${string}`;
}Membership.Plan
Represents a membership plan that customers can purchase.
namespace Membership {
export type Plan = {
id: Plan.Id; // e.g. "mp_example"
organizationId: Organization.Id;
name: string;
description: string;
priceCents: number;
introOfferType?: Plan.IntroOfferType;
renewalPeriod?: Plan.Period;
classLimit?: number;
classRefreshPeriod?: Plan.Period;
guestPassLimit?: number;
guestPassRefreshPeriod?: Plan.Period;
};
export namespace Plan {
export type Id = `mp_${string}`;
export type Period = `${number} ${Period.Unit}`; // e.g. "1 month"
export namespace Period {
export type Unit = "day" | "week" | "month" | "year";
}
export type IntroOfferType = "pre-booking" | "pre-membership" | "pre-self";
}
}PaymentMethod
Represents a payment method attached to a customer used for purchases.
type PaymentMethod = {
id: PaymentMethod.Id; // e.g. "pm_example"
type: PaymentMethod.Type;
details: {
brand: PaymentMethod.Card.Brand;
lastFour: string;
exp: `${string}/${string}`;
};
};
namespace PaymentMethod {
export type Id = `pm_${string}`;
export type Type = "unknown" | "card";
export namespace Card {
export type Brand = "visa" | "mastercard" | "amex" | "discover";
}
}Theming
You can customize the appearance of Vygor Elements to match your brand's styling. Theme options are passed during the initialization of the SDK via the theme property in the options object.
// Example theme configuration
Vygor.init("o_example", {
theme: {
baseUnit: "8px", // Base unit for scaling
shape: {
borderRadius: 2, // Multiplier for border radius
},
spacing: {
baseUnit: 1, // Multiplier or absolute value for spacing
panelGap: 2.5, // Multiplier for gap between panels
},
card: {
padding: 2, // Multiplier for card padding
borderRadius: 2, // Multiplier for card border radius
},
font: {
family: "MyCustomFont" || "google:Inter", // Font family name (can use Google Fonts)
faces: [
{
family: "MyCustomFont",
src: "url(/path/to/MyCustomFont.woff2)",
weight: 400,
style: "normal",
},
],
weights: {
semibold: 600,
bold: 700,
},
},
colors: {
background: "#ffffff",
onBackground: "#111111",
primary: "#6200ea",
onPrimary: "#ffffff",
border: "#cccccc",
success: "#00c853",
onSuccess: "#000000",
warning: "#ffab00",
onWarning: "#000000",
error: "#d50000",
onError: "#ffffff",
},
},
});Below is a breakdown of the available theme properties:
Root Properties
baseUnit:string- The universal base unit for scalar values. Change this to scale all spacing and sizing globally.
- Default:
"0.5rem"or"8px"
shape
borderRadius:number- Universal default border radius for all components, applied as a multiplier of the root
baseUnit. - Default:
2.5
- Universal default border radius for all components, applied as a multiplier of the root
spacing
baseUnit:number | string- The base unit specifically for the spacing system. If a
number, it acts as a multiplier of the rootbaseUnit. If astring, it's used as an absolute CSS unit (e.g.,10px). - Default:
1
- The base unit specifically for the spacing system. If a
panelGap:number- The gap between panels (e.g., in checkout elements), applied as a multiplier of the
spacing.baseUnit. - Default:
2
- The gap between panels (e.g., in checkout elements), applied as a multiplier of the
card
padding:number- The padding inside card components, applied as a multiplier of the
spacing.baseUnit. - Default:
2.5
- The padding inside card components, applied as a multiplier of the
borderRadius:number- The border radius for card components, applied as a multiplier of the root
baseUnit. - Default:
2.5
- The border radius for card components, applied as a multiplier of the root
font
family:`google:${string}` | string- The primary font-family name to use. Use the
google:prefix to load fonts from Google Fonts (e.g.,google:Inter). Otherwise, provide a standard CSS font-family string. - Default:
"Figtree"
- The primary font-family name to use. Use the
faces:Array<{ family: string; src: string; weight: number; style?: "normal" | "italic" | "oblique" }>- Allows loading external font faces. Provide an array of objects, each defining a font face. The
srcURL must be accessible by the Vygor endpoint origin (production: "https://vygorai.com").
- Allows loading external font faces. Provide an array of objects, each defining a font face. The
weights:{ semibold?: number; bold?: number }- Override the default font weights used within elements.
semibold: Default:600bold: Default:700
- Override the default font weights used within elements.
colors
Provide valid CSS color strings for the following properties:
background: The main background color for elements. Default:"#1f1e1d"onBackground: Text/icon color onbackground. Will be derived from background if not set. Default:"#eeeeee"primary: Main accent color used for buttons, highlights, and interactive elements. Default:"#ccc395"onPrimary: Text/icon color onprimarybackgrounds. Will be derived from primary if not set. Default:"#1f1e1d"border: Default border color for separators and outlines. Will be derived from background if not set. Default:"#484848"success: Color for success states, confirmations, and positive feedback. Default:"#00900b"onSuccess: Text/icon color onsuccessbackgrounds. Will be derived from success if not set. Default:"#ffffff"warning: Color for warning states, cautions, and alerts. Default:"#ddd900"onWarning: Text/icon color onwarningbackgrounds. Will be derived from warning if not set. Default:"#1f1e1d"error: Color for error states, failures, and destructive actions. Default:"#ff3d00"onError: Text/icon color onerrorbackgrounds. Will be derived from error if not set. Default:"#ffffff"
Overrides
For more granular control beyond theming, you can use overrides to customize specific components within Vygor Elements. Overrides are passed during initialization via the overrides property in the options object.
Vygor.init("o_example", {
theme: {
// ... theme options
},
overrides: {
button: {
"primary": {
style: {
color: "#000000",
background: "#ffffff",
},
},
"text-primary": {
style: {
color: "#6200ea",
},
},
},
},
});Button Overrides
You can customize the appearance of buttons within Vygor Elements by overriding their default styles.
button.primary
Overrides styles for primary action buttons (e.g., "Complete Purchase", "Book Now").
style.color:string- Text color for primary buttons.
- Default:
"var(--strong-on-primary)"(derived from theme)
style.background:string- Background color for primary buttons.
- Default:
"var(--primary)"(derived from theme)
button.text-primary
Overrides styles for text-based primary action buttons (buttons without background fills).
style.color:string- Text color for text-based primary buttons.
- Default:
"var(--primary)"(derived from theme)
Example
// Customize button styles to match a specific brand
Vygor.init("o_example", {
theme: {
colors: {
primary: "#6200ea",
onPrimary: "#ffffff",
},
},
overrides: {
button: {
"primary": {
style: {
color: "#ffffff",
background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
},
},
"text-primary": {
style: {
color: "#667eea",
},
},
},
},
});Advanced Usage
Multiple Vygor.Clients
You can create multiple clients targetting different organization IDs and endpoints with the Vygor.Client class
Example:
const client = new Vygor.Client(`o_example`);
// or
const client = new Vygor.Client(`o_example`, {
endpoint: "https://otherendpoint.com",
});
client.fetchSchedule().then(() => {
// ...
});deferInitialization
If you need a reference to a client outside of the scope it can be initialized, you can use Vygor.Client.deferInitialization.
Example:
const client = Vygor.Client.deferInitialization();
// ...
client.init("o_example", {
endpoint: "https://otherendpoint.com",
});
// ...
client.fetchSchedule().then(() => {
// ...
});