Part 2: Features & Plans
This tutorial will walk you through creating your first Feature and Plan, then using them in your Surface decision. Features are the individual capabilities or functionalities of your product, while Plans are a collection of features that define access levels for specific offerings or packages.
Prerequisites
Before you begin, ensure you have the following:
- Every step from Part 1 completed
Create a Feature
To create your first Feature:
- Navigate to the Features page in the MonetizationOS console
- Click "Add Feature"
- Give it a name, e.g. "Widget"
- Click "Create Feature"
You will now have a newly created Feature. Features contain Feature Properties, the core building blocks for access and configuration in your application.
By default, all features have an Enabled property with a fallback value of Off (false). This is to allow you to easily control access to a feature and add metering in Plans or Workflows.
Add a new Feature Property
Next, let's add a new Feature Property to your Feature:
- In your newly created Feature, click "Add new property"
- Give it a name, e.g. "Premium"
- Select the type as
Boolean - Leave the other fields as default and click "Save"
Make a Surface decision
Rerun the same cURL command as Part 1 to see the updated response with your feature included.
You should receive a response including your new feature, similar to the following:
{
...
"features": {
"widget": {
"featureId": "feat_abcd1234",
"featureSlug": "widget",
"properties": {
"premium": {
"type": "boolean",
"value": false,
"isFallback": true
},
"enabled": {
"counterId": "default:feat_abcd1234.enabled",
"type": "meterable",
"hasAccess": false,
"isFallback": true
}
}
}
},
...
}Take note of the features section in the response, which now includes your "Widget" feature with its properties.
All features are included in surface decision responses, even if they are not explicitly used in a workflow or assigned by a plan.
Create an Anonymous Plan
To create your first Plan:
- Navigate to the Plans page in the MonetizationOS console
- Click "Add Plan"
- Give it a name, e.g. "Anonymous"
- Click "Create"
- In the Plan Assignments section, click "Assign to anonymous users"
Now we have a Plan that is automatically assigned to all anonymous users, but it doesn't do anything yet.
Let's change that by configuring the Anonymous Plan to include the "Widget" Feature, with "Enabled" and "Premium" set to Off (false).
- Navigate to the Configure Features tab
- Click "Configure Features"
- Select the "Widget" Feature
- Ensure that the "Enabled" and "Premium" properties are set to Off (
false) - Click "Update Plan"
This may seem counterintuitive since the fallback value for both "Enabled" and "Premium" properties is already Off (false),
but this step is important to ensure that the plan explicitly defines these values so any potential changes to fallback values don't have unintended effects.
Make another Surface decision
Rerun the same cURL command as Step 2 to see the updated response with your new anonymous plan applied.
You should receive a response with changes similar to the following:
{
...
"features": {
"widget": {
"featureId": "feat_abcd1234",
"featureSlug": "widget",
"properties": {
"premium": {
"type": "boolean",
"value": false,
"isFallback": true
"isFallback": false
},
"enabled": {
"counterId": "default:feat_abcd1234.enabled",
"type": "meterable",
"hasAccess": false,
"isFallback": true
"isFallback": false
}
}
}
},
...
}Notice now that both properties of the "Widget" feature have isFallback: false, indicating that their values are now being determined by a Plan or Workflow.
Registered Plan Assignment
Next, let's create a Plan for registered users.
- Navigate to the Plans page in the MonetizationOS console
- Click "Add a Plan"
- Give it a name, e.g. "Registered"
- Click "Create"
- In the Plan Assignments section, click "Assign to registered users"
This Plan will now be automatically assigned to all registered users. Let's also configure the "Widget" Feature.
- Navigate to the Configure Features tab
- Click "Configure Features"
- Select the "Widget" Feature
- Toggle the "Enabled" property to On (
true) - Click "Update Plan"
Make a registered Surface decision
To make a registered Surface decision update the previous cURL command, replacing anonymousIdentifier with userIdentifier.
Note: userIdentifier only works in Surface decisions made using a Secret API key. JWT tokens can be used for
identifying users in client-side requests with a Public API key.
curl -X POST https://api.monetizationos.com/api/v1/surface-decisions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"surfaceSlug": "$SURFACE_SLUG",
"identity": {
"userIdentifier": "test@example.com"
}
}'You should receive a response with changes similar to the following:
{
...
"identity": {
"authType": "anonymous",
"identifier": "test",
"isAuthenticated": false,
"authType": "provided",
"identifier": "test@example.com",
"isAuthenticated": true,
"jwtClaims": {}
},
"features": {
"widget": {
"featureId": "feat_abcd1234",
"featureSlug": "widget",
"properties": {
"premium": {
"type": "boolean",
"value": false,
"value": true,
"isFallback": false
},
"enabled": {
"counterId": "default:feat_abcd1234.enabled",
"type": "meterable",
"hasAccess": false,
"hasAccess": true,
"isFallback": false
}
}
}
},
...
}As you can see, the Surface decision now reflects the "Registered" Plan assignment. This is a good time to mention the Observability capabilities of MonetizationOS. Every event that occurs in the system is logged and can be inspected in the Observability page of the console.
Update our Surface decision
Finally, let's use the "Widget" Feature and Identity details in the "Hello, World!" Surface workflow from Part 1.
Replace the existing code with the following, and click "Update Workflow" to save your changes:
const workflow: SurfaceWorkflow = async ({
features, // All features and properties are available in the decision
identity, // User identity details
}) => {
return {
properties: {
userMessage: `Hello, ${identity.identifier}`,
isAuthenticated: identity.userType === "authenticated",
widgetAccess: features.widget.enabled.hasAccess,
premiumWidgets: features.widget.premium,
},
};
};
export default workflow;You may notice that features and identity were already available in the Surface decision response, so why use them in a workflow? Using features and identity in a workflow allows you to implement custom business logic and derive new properties based on multiple data points. Externalizing this logic to a workflow also means it can be updated without requiring code changes or deployments in your application.
Make one more Surface decision
Rerun the same cURL command as Step 6 to see the updated response with your new Surface workflow properties.
You should receive a response with changes similar to the following:
{
...
"surfaceBehavior": {
"properties": {
"userMessage": "Hello, World!",
"userMessage": "Hello, test@example.com",
"isAuthenticated": true,
"widgetAccess": true,
"premiumWidgets": false
}
},
...
}Try changing the cURL request body back to using an anonymousIdentifier to see how the response changes based on different users.
You've reached the end of Part 2 of this tutorial. You have successfully created a Feature, assigned it to Plans for anonymous and registered users, and made Surface decisions using anonymous and user identifiers.
Proceed to Part 3 to continue the tutorial.