Background: Members with a Wix Pricing Plan can create listings. These listings are stored in a CMS collection & displayed via dynamic pages. The collection has a Boolean field, used to manually hide a listing Goal: When their plan ends, their listing should be hidden automatically
Suggestions of approaches (as a rookie coder)
When plan ends, user’s corresponding collection item auto modifying itself
1.1) Using Wix Automations: Can you modify a CMS item directly with no code? Seems no option yet. Or is there?:
There are two ways to do this depending on the volume of users and the number of items that you have in your CMS:
#1 - Using event hooks
Similar to the approach shown by the AI, you can triggert a bulk update to toggle off (hide) one or more listings belonging to a particular user when their pricing plan subsciption ends. And restart it if they sign up for another subscription.
OR
#2 - Fetching data on the fly
In this you don’t need to have a toggle on / off column in your CMS, your code will directly fetch all active subscriptions and will automatically filter your entire list to show only those listings that belong to a user with an active subsription.
This latter method is what I have used in one of my client’s site, which is pretty content heavy and required this exact same functionaity. And the second option works like a charm. In my personal opinion, it is much more reliable, accurate and consistent as compared to the data hook method, since it runs the code and fetches live, real-time member subscription data every time the page loads.
No, there is no such option as of now to directly modify CMS items or control their visibility simply through automations, without using any code.
I’m not aware of a guide or a tutorial that demonstrates this use case, but I can explain the underlying logic flow for method #2, which you can use as a foundation to write your code.
When the page loads, fetch all your active subscriptions using using the managementListOrders() function in the backend.
Fetch the memberId associated with each subscription and form an array that you will return to the frontend.
Based on how you’ve mapped the listings with your users, you can either use this array and directly pass it as a filter for the _owner field in your dataset, or fetch the login email for these subscribers and then filter your dataset accordingly.
As barely a beginner coder, after trying & learning this for a while I found it’s too advanced for me. SDK AI assistant gave the following code. Nothing has worked yet. Can anyone help fix this?
import { orders } from "@wix/pricing-plans";
export async function getActiveOrders() {
try {
const options = {
orderStatuses: ['ACTIVE'], // Filter for active orders
};
const ordersList = await orders.managementListOrders(options); //!error under options
return ordersList.orders.map(order => order.buyer.memberId); // Extract member IDs
} catch (error) {
console.error(error);
}
}
$w.onReady(async function () {
const memberIds = await getActiveOrders(); // Get member IDs with active plans
const filter = wixData.filter().hasSome('_owner', memberIds); // Adjust 'ownerId' to match your dataset field
$w('#listingsDataset').setFilter(filter);
});
I haven’t started using the SDK syntax yet, but from what I can see, the managementListOrders() function requires elevated and here’s how you would set it up using Velo:
fetchOrders.jsw (backend):
import { orders } from 'wix-pricing-plans.v2';
import * as wixAuth from 'wix-auth';
export async function elevatedManagementListOrders(options) {
const elevatedOrders = wixAuth.elevate(orders.managementListOrders);
try {
const result = await elevatedOrders(options);
return result.orders;
} catch (error) {
console.log(error);
}
}
Page Code (frontend):
import wixData from 'wix-data';
import { elevatedManagementListOrders } from 'backend/fetchOrders'
$w.onReady(async function () {
let options = {
orderStatuses: ["ACTIVE"]
}
var activeOrderList = await elevatedManagementListOrders(options);
// Implement your data filtering logic here
});
Hi, I tried modifying this for a while, it doesn’t filter based on those owners. With too many unknowns at many stages I don’t know what to do. Appreciate your help anyway
Hi, I managed some code to make this work using your 2nd approach, so many thanks. Unfortunately as it redirects after the load, it reveals the page for a moment too long. So I’ve tried to do this using routers instead. Could you please suggest a solution; my post showing latest attempts- How to Redirect some Dynamic Item pages using Routers
Hi, hope you’ve been well. I just have some technical questions about your working solution #2 & about filters. (I’m a noob coder & would like to know how these work, so all this code works reliably)
Re velo code filters: Do filters apply at each load of results? The filters are placed inside an $w.onReady(async function & items per load are 20.
Re your solution #2’s reliability: The API ref of managementListOrders( ) says it Retrieves a list of up to 50 pricing plan orders & details, given the specified sorting & filtering
.
So my concerns are; if the code inside the $w.onReady(async function will reliably query & filter at each load.. if there are more than 50 pricing plan orders, will it not work? Could you please explain if these would reliably work & at what limits they’ll not; referring to how things generally work when some results are queried & loaded?
Working code
.jsw fetch orders
import { orders } from 'wix-pricing-plans.v2';
import * as wixAuth from 'wix-auth';
export async function elevatedManagementListOrders(options) {
const elevatedOrders = wixAuth.elevate(orders.managementListOrders);
try {
const result = await elevatedOrders(options);
return result.orders;
} catch (error) {
console.log(error);
}
}
Yes, most Velo APIs have a query limit of 50 items per call, so is the case with the managementListOrders API. Which means if there are a total of 125 inactive plans, you will get the first 50 in the initial call, and the remaining 75 would have to be fetched again, by passing in an offset of 50, so that the next query result returns another 50 inactive plans from number 51 - 100, so now your offset for the next call would be 100… and you gotta keep on going like this until the value of the total field in the pagingMetadata object equals 0, indicating no more plans match the provided offset, which would mean that we have iterated through all of them.
Now this is where I’ve spotted a critical flaw in the inverted logic that you are using.
Like I had mentioned earlier,
If you would have fetched the first 50 “ACTIVE” plans and passed them to the filter in the frontend, you could have set the items per load to 50 as well and could have coded the LOAD MORE button to fetch the next batch of 50 active subscriptions using your backend code, and the cycle would’ve continued.
However, you have inverted the logic, so now you are fetching the plans that are NOT ACTIVE and are passing that as a filter parameter to your page. What’s going to happen here is that - if you have 125 inactive plans, you are only getting the first 50, so unless you fetch the remaining 75, those listings will continue to show up on your page - despite of being inactive. I don’t know if your status field might be of any help here - but this inverted logic has a high possibility of inaccuracy.
So I will recommend going the way that I suggested initially, i.e. query ACTIVE plans with a limit of 20 or 50 whichever you prefer, and use the same number as the value for items per load, and keep adding the total number of plans queried on each click and pass that as the offset value while querying the next set.
Thank you so much for explaining all that clearly & pointing out these concerns. I should work on a more reliable solution for this.
You’re a gem💎 in this community.