Feature gating
Feature gating allows you to control access to specific functionality in your app based on a merchant's subscription plan. This approach enables you to create tiered offerings, encourage upgrades, and ensure merchants can only access the features they've paid for.
What is feature gating?
Feature gating is the practice of conditionally enabling or restricting access to certain features or capabilities based on predetermined criteria. In Mantle, these criteria are typically tied to:
- The merchant's current subscription plan
- Usage-based limits associated with features
- Custom entitlements configured for specific merchants
Implementation strategies
There are several ways to implement feature gating in your app:
1. Frontend conditional rendering
Control what UI elements and features are displayed to merchants:
import { useMantle } from '@heymantle/react';
function AdvancedReporting() {
const { isFeatureEnabled } = useMantle();
const hasAdvancedReporting = isFeatureEnabled({
featureKey: 'advanced_reporting'
});
return (
<div>
<h2>Reports</h2>
{/* Basic reports shown to everyone */}
<BasicReports />
{/* Advanced reports only shown if feature is enabled */}
{hasAdvancedReporting ? (
<AdvancedReports />
) : (
<UpgradePrompt feature="advanced_reporting" />
)}
</div>
);
}2. Backend route protection
Secure API endpoints or server-side functionality:
app.post('/api/advanced-reports', async (req, res) => {
try {
// Check if merchant has access to advanced reporting
const hasFeature = await mantleClient.isFeatureEnabled({
featureKey: 'advanced_reporting',
customerApiToken: req.headers['x-customer-api-token']
});
if (!hasFeature) {
return res.status(403).json({
error: 'Feature not available on your current plan'
});
}
// Feature is available, proceed with generating report
const report = await generateAdvancedReport(req.body);
return res.json({ report });
} catch (error) {
return res.status(500).json({ error: error.message });
}
});3. Middleware approach
Create reusable middleware for feature checks:
function requireFeature(featureKey) {
return async (req, res, next) => {
try {
const hasFeature = await mantleClient.isFeatureEnabled({
featureKey,
customerApiToken: req.headers['x-customer-api-token']
});
if (!hasFeature) {
return res.status(403).json({
error: `Feature '${featureKey}' not available on your current plan`
});
}
next();
} catch (error) {
return res.status(500).json({ error: error.message });
}
};
}
// Use middleware to protect routes
app.post('/api/advanced-reports', requireFeature('advanced_reporting'), (req, res) => {
// Feature check already passed, generate report
const report = generateAdvancedReport(req.body);
return res.json({ report });
});4. Limit-based gating
For features with numerical limits:
async function createProduct(productData) {
const limit = await mantleClient.limitForFeature({
featureKey: 'product_limit'
});
const customer = await mantleClient.getCustomer();
const used = customer.usage['Product limit']?.currentValue || 0;
if (used >= limit) {
throw new Error('Product limit reached. Please upgrade your plan for more products.');
}
// Within limits, proceed with product creation
const product = await actuallyCreateProduct(productData);
// Track usage
await mantleClient.sendUsageEvent({
eventName: 'product_created',
properties: { productId: product.id }
});
return product;
}Upgrade prompts
When a merchant attempts to access a gated feature, provide clear upgrade paths:
function UpgradePrompt({ feature }) {
const { plans } = useMantle();
// Find plans that include this feature
const eligiblePlans = plans.filter(plan =>
plan.features[feature]?.value === true
);
return (
<Card>
<Text variant="heading">Unlock Advanced Features</Text>
<Text>This feature requires an upgrade to access.</Text>
<Stack>
{eligiblePlans.map(plan => (
<PlanCard
key={plan.id}
plan={plan}
primaryAction={{
content: `Upgrade to ${plan.name}`,
onAction: () => handleUpgrade(plan.id)
}}
/>
))}
</Stack>
</Card>
);
}Best practices
- Check early, check often - Validate feature access early in your request lifecycle
- Provide clear feedback - Explain why features are unavailable and how to access them
- Cache check results - Store feature availability results to reduce API calls when appropriate
- Handle edge cases - Account for error scenarios and network issues
- Be consistent - Apply the same gating patterns across your application
- Keep UI in sync - Ensure interfaces don't show options for features merchants can't access
Updated over 1 year ago