Velo Tutorial: Using the Pricing Plans API for Pricing Plan Ordering and Payment
- Working with dynamic pages and multiple collections.
- Customizing the order and payment flow by adding lightboxes.
- Responding to the event of a plan being purchased.

Overview
- The Pricing Plans app.
- When adding the Pricing Plans app, a Plans collection with a list of membership plans for sale was automatically added.
- A collection for adding more details to each plan, such as testimonials and images.
- A collection for tracking purchases.
- A Collection & Repeater page. The repeater displays plans from the Testimonials collection, which references the Plans collection. Visitors can click a See More button for more details about a plan.
- A Dynamic page. This page displays information from both the Plans collection and the Testimonials collection. Visitors can click a Buy Now button to purchase a plan.
- A lightbox that displays before processing with the purchase, and a different lightbox that displays after ordering a free plan.
- An event for logging successful purchases in a collection.
Then we added code to do the following:
- When a visitor clicks the See More button, the button's click event handler calls the
to()
function to open the dynamic page. - When a visitor clicks the Buy Now button for a free plan, the button's click event handler calls the
createOnlineOrder()
function to order the plan and opens a congratulations lightbox. - When a visitor clicks the Buy Now button for a plan that costs money, the button's click event handler opens a confirmation lightbox.
- When a visitor clicks Yes, the button's event handler calls the
createOnlineOrder()
function to order the plan. - The function checks if the visitor is logged in, and if not, prompts for login.
- When the visitor is logged in, the function creates, and returns, a promise that resolves to an
order
object. - A payment procedure is initiated using the ID from the
order
object, causing a payment window to appear. - The visitor enters payment information and completes the transaction. This triggers the
onPlanPurchased()
event, which receives aPlanPurchasedEvent
object. - The function logs an event in a collection using data from the
PlanPurchasedEvent
object.

Before You Start
- Set up Wix Payments on your site. We also recommend that you understand the typical payment process before proceeding.
- Add the Pricing Plans app to your site.
Step 1: Set up Collections
- A PaidPlans/Plans collection, for membership plans.
- A Testimonials collection, for each plan's testimonials and images.
- A PlanEvents collection, for logging each successful purchase.
The PaidPlans/Plans Collection

Additional Collections
In our new Testimonials collection, we added a PlanName reference field that references the Slug field in our Plans collection. The reference field links the testimonials and plan images to the corresponding plan in the Plans collection.

PlanEvents Collection
We created a collection to track successful purchases. We added a text field called Data to the collection.
We created code in an events.js page to insert the live data from the PlanPurchasedResult
object into the Title and Data fields. This code is explained in detail in Step 4.
This is what some of the live data in our PlanEvents collection looks like, after we have made a few purchases.

Step 2: Set up the Collection & Repeater Page
Design the Page
- A repeater to display the plans.
- Text and image elements in the repeater to display the name, price, and picture of each plan.
- A See More button in the repeater to display the selected plan using a dynamic page. (Instructions for creating the dynamic page are provided in Step 5.)
- A dataset connected to our Testimonials collection for connecting data in the collection to the repeater.

Add Event Handlers
- In our page's onReady( ) function, we added an onClick event handler that will run when a See More button is clicked.
Code the Page
1// For navigating to a dynamic page:
2import wixLocation from 'wix-location';
3
4
5$w.onReady( function () {
6
7 // If the site visitor clicks a plan's See More button,
8 // the browser relocates to that plan's dynamic page.
9
10 $w("#button1").onClick( (event) => {
11 let $item = $w.at(event.context);
12 let clickedItemData = $item("#dataset1").getCurrentItem();
13 let slug = clickedItemData.planName.slug;
14
15 // We customize the URL of the dynamic Plans page to match this code.
16 wixLocation.to('/gameplans/'+slug);
17 } );
18} );

Step 3: Customize the Purchase of a Plan
To demonstrate that we can customize the flow of a paid plan purchase, we will use the createOnlineOrder()
function instead of the startOnlinePurchase()
function.
- With
createOnlineOrder()
, we can control and customize aspects of the order process. - With
startOnlinePurchase()
, we use the standard paid plan functionality as provided with the Wix Paid Plans app. ThestartOnlinePurchase()
function provides a standard payment flow that starts with ordering and automatically continues to payment. This gives you less opportunity to customize, but requires less coding and design.
As part of our customization, we added two lightboxes to our site (to be used in Step 5).
- The Confirm lightbox displays information about the currently-selected plan, and provides buttons for continuing or canceling the purchase.
- The Congrats lightbox lets you know that you purchased a free plan.
In this step, we kept it simple. However, this is the opportunity for you to really customize the process as you like.

Step 4: Set up an Event Handler in the Backend to Log Purchases
When a plan is successfully purchased or ordered, an onPlanPurchased
event is triggered.
In our example, when this event is fired, we log the details about the purchase by inserting the information in our PlanEvents
collection.
Here is sample backend code that we put in an events.js
file.
1/*****************************
2 * Backend code in events.js *
3 *****************************/
4
5// For inserting data into a collection.
6import wixData from 'wix-data';
7
8// The onPlanPurchased() event is fired when a plan
9// is purchased, or a free plan is ordered.
10// Get the order information
11// from the event's order object.
12
13export function wixPricingPlans_onPlanPurchased(event) {
14
15 // The PlanEvents collection has a title field,
16 // in which we insert the type of transaction.
17 // The collection also has a data field,
18 // where we will insert information about the order
19 // from the event's order object (json).
20
21 if (event.order.price.amount === 0) {
22 let orderData = {
23 "title": "Free plan purchased",
24 "data": event.order
25 };
26 wixData.insert("PlanEvents", orderData);
27
28 } else {
29 let orderData = {
30 "title": "Regular plan purchased",
31 "data": event.order
32 };
33 wixData.insert("PlanEvents", orderData);
34 }
35}
Step 5: Customize your Dynamic Page

Design the Page
- Text and image elements to display the details of each plan from the PaidPlans/Plans collection and the Testimonials collection.
- A dataset for the Testimonials collection.
The Testimonials collection is filtered by planName so that any data displayed from the Testimonials collection matches the currently-displayed plan from the Plans collection. - A Buy Now button to order the plan.

Add Event Handlers
- In the Properties & Events panel of the repeater, we added an
onItemReady
event handler that will run when the repeater is ready to be loaded. - In the Properties & Events panel of the
buyNow
button, we added anonClick
event handler that will run when the Buy Now button is clicked.

Code the Page
The code on our dynamic page consists of five parts:
-
Imports for the APIs used in the rest of the code.
-
An
onReady()
event handler for making sure all page elements are available. -
Retrieval of the current plan's data from the Plans collection in a
currentPlanObject
object. -
Check if the visitor is logged in. If necessary, the site prompts the visitor to log in.
-
A function for processing the order of free plans and the purchase of plans that cost money.
We used the following APIs:
wix-members
- For getting information about the current member and for logging members in and out.wix-window
- For lightboxes.wix-pricing-plans
- For ordering and purchasing pricing plans.wix-pay
- For processing payments.
1import wixWindow from 'wix-window';
2import wixPay from 'wix-pay';
3import {checkout} from 'wix-pricing-plans';
4import {authentication} from 'wix-members';
onReady()
Event Handler
In this example, there is no special setup we need to do for our elements. So we used the standard onReady()
event handler.
1$w.onReady( () => {
2 ...
3 ...
4 //Insert code here.
5 ...
6 ...
7} );
getCurrentItem()
Function
Next, we retrieved the current plan's data from the PaidPlans\Plans collection using the Wix Dataset getCurrentItem()
function with the dynamic dataset on the page. We stored the information in a currentPlanObject
object variable. Now we have access to the information we need about the plan to continue processing the order or purchase.
If you copy the code snippet below, make sure to change the dataset name to match your own.
1$w.onReady( () => {
2 ...
3 ...
4
5 const currentPlanObject = $w("#dynamicDataset").getCurrentItem();
6 const planId = currentPlanObject._id;
7 const planPrice = currentPlanObject.price;
8 ...
9 ...
10 //Insert more code here.
11 ...
12 ...
13} );
onClick()
Event Handler
Most of the logic in our page is contained in the onClick()
event handler of the buyNow
button.
If you copy the code snippet below, make sure to change the button name to match your own.
1$w.onReady( () => {
2 ...
3 ...
4
5 const currentPlanObject = $w("#dynamicDataset").getCurrentItem();
6 const planId = currentPlanObject._id;
7 const planPrice = currentPlanObject.price;
8 ...
9 ...
10 $w('#buyNow').onClick((event) => {
11
12 ...
13 //Insert code for handling the button click here.
14 ...
15
16 });
17 ...
18 ...
19 //Insert more code here.
20 ...
21 ...
22} );
We don't want to sell plans to visitors that are not logged in. So we used authentication.loggedIn()
to see if the visitor is logged in.
- If the visitor is not logged in, we used
authentication.promptLogin()
function to ask the visitor to log in. Then we can call a function that we namedprocessPlan()
to continue. - If the visitor is already logged in, we can immediately call the
processPlan()
function.
1$w.onReady( () => {
2
3 const currentPlanObject = $w("#dynamicDataset").getCurrentItem();
4 const planId = currentPlanObject._id;
5 const planPrice = currentPlanObject.price;
6
7 $w('#buyNow').onClick((event) => {
8
9 let isLoggedIn = authentication.loggedIn();
10
11 if (!isLoggedIn) {
12 authentication.promptLogin().then(() => {
13 processPlan(planId, planPrice);
14 })
15 } else {
16 processPlan(planId, planPrice);
17 }
18 });
19});
Now let's look at the function we created, processPlan()
, to get payment for the plan.
We chose to use the createOnlineOrder()
function for processing because we wanted to control and customize the entire order/purchase flow. When orderPlan()
is called, and a plan is successfully purchased or ordered, an onPlanPurchased
event is triggered.
This is where you can enter your own code to customize your own order/purchase flow.
In our example, we customized the flow by:
- If the plan costs money, asking for member confirmation using the
Confirm
lightbox. If the member confirms, we callcreateOnlineOrder()
and then process payment with the Wix PaystartPayment
function. - If the plan is free, using the
Congrats
lightbox to let the member know the plan order is successful.
The order details are contained in the orderObject
object.
When copying this snippet, make sure to change the names of your lightboxes to match your own.
1function processPlan(myId, myPrice) {
2
3 if (myPrice > 0) {
4 checkout.createOnlineOrder(myId).then(orderObject => {
5 wixWindow.openLightbox("Confirm", orderObject)
6 .then((goForIt) => {
7 if (goForIt) {
8 wixPay.startPayment(orderObject.wixPayOrderId);
9 }
10 });
11 })
12 } else {
13 checkout.createOnlineOrder(myId).then(orderObject => {
14 wixWindow.openLightbox("Congrats", orderObject);
15 })
16 }
17}
1import wixWindow from 'wix-window';
2import wixPay from 'wix-pay';
3import {checkout} from 'wix-pricing-plans';
4import {authentication} from 'wix-members';
5
6$w.onReady(function () {
7
8 const currentPlanObject = $w("#dynamicDataset").getCurrentItem();
9 const planId = currentPlanObject._id;
10 const planPrice = currentPlanObject.price;
11
12 $w('#buyNow').onClick((event) => {
13
14 let isLoggedIn = authentication.loggedIn();
15
16 if (!isLoggedIn) {
17 authentication.promptLogin().then(() => {
18 processPlan(planId, planPrice);
19 })
20 } else {
21 processPlan(planId, planPrice);
22 }
23
24 });
25});
26
27function processPlan(myId, myPrice) {
28
29 if (myPrice > 0) {
30 checkout.createOnlineOrder(myId).then(orderObject => {
31 wixWindow.openLightbox("Confirm", orderObject)
32 .then((goForIt) => {
33 if (goForIt) {
34 wixPay.startPayment(orderObject.wixPayOrderId);
35 }
36 });
37 })
38 } else {
39 checkout.createOnlineOrder(myId).then(orderObject => {
40 wixWindow.openLightbox("Congrats", orderObject);
41 })
42 }
43}
Tip: Want to use the standard, "out of the box" Wix flow for letting visitors purchase a plan?
- Use the
startOnlinePurchase()
function in the code instead of thecreateOnlineOrder()
function. - No need to call
wixPay
. ThestartOnlinePurchase( )
function does that for you.
API List
- wix-pricing-plans - For ordering and purchasing pricing plans.
- wix-pay - For payments.
- wix-members - Gets information about the current member and for logging members in and out.
- wix-data - For inserting into collections.
- wix-location - For navigation.