Full Stack Experiments

Implementing Convert's Full Stack JavaScript SDK: Real-World Examples

Master Convert's JavaScript Full Stack SDK with real-world A/B testing examples for pricing, trials, payments, analytics, and persistent storage.

In This Article You Will:

Introduction

Convert's JavaScript Full Stack SDK provides a powerful way to implement experimentation and feature management in your applications. This guide presents five real-world implementation examples to help you understand how to effectively use the SDK for various business scenarios.

These examples demonstrate how to properly implement Convert's SDK for:

  • Subscription pricing tests
  • Trial period experiments
  • Payment recovery workflows
  • Persistent data storage
  • Analytics integration

Each example includes detailed business context, implementation code, and best practices.

Prerequisites

Before diving into the examples, ensure you have:
✅ A Convert account with access to the Full Stack product
✅ Node.js installed in your environment
✅ Basic knowledge of JavaScript and async/await patterns

Installation

Install the Convert JavaScript SDK using npm:

npm install @convertcom/js-sdk

Or using yarn:

yarn add @convertcom/js-sdk

Example 1: Subscription Tier Pricing Test

Business Context

The marketing team is implementing a strategic A/B test to determine if a premium pricing model can increase overall revenue without significantly reducing conversion rates.

The experiment compares:

  • Control: $9.99/month subscription
  • Variant: $12.99/month subscription with additional premium features

This test aims to evaluate price elasticity and determine the value perception of enhanced features among users.

Implementation

const Convert = require('@convertcom/js-sdk').default;

// SDK initialization
const convert = new Convert({
  sdkKey: process.env.CONVERT_SDK_KEY,
  environment: 'production'
});

// Get pricing plan based on experiment
async function getSubscriptionPlan(userId) {
  try {
    const experimentId = 'subscription_pricing_test';
    const userContext = await convert.createContext({ userId });
    const result = await userContext.runExperience(experimentId);
    const variant = result.variationKey;

    // Define plans
    const pricingPlans = {
      control: { price: 9.99, code: 'BASIC', features: ['Core Features', 'Basic Support'] },
      variant_1: { price: 12.99, code: 'PREMIUM', features: ['Core Features', 'Priority Support', 'Enhanced Storage'] }
    };

    // Track exposure event
    await userContext.trackConversion('experiment_exposed', {
      conversionData: [{
        experienceId: experimentId,
        variationId: result.variationId
      }]
    });

    return pricingPlans[variant];

  } catch (error) {
    console.error('Convert SDK Error:', error);
    return { price: 9.99, code: 'BASIC', features: ['Core Features', 'Basic Support'] };
  }
}

// Example implementation in pricing page route
app.get('/pricing', async (req, res) => {
  const userId = req.session.userId;
  const pricingPlan = await getSubscriptionPlan(userId);

  res.render('pricing', {
    monthlyPrice: pricingPlan.price,
    planCode: pricingPlan.code,
    features: pricingPlan.features
  });
});

// Track conversion when user subscribes
app.post('/subscribe', async (req, res) => {
  const userId = req.session.userId;
  const selectedPlan = req.body.planCode;
  const price = selectedPlan === 'PREMIUM' ? 12.99 : 9.99;

  try {
    const userContext = await convert.createContext({ userId });
    await userContext.trackConversion('subscription_purchased', {
      conversionData: [{
        amount: price,
        transactionId: orderId
      }]
    });
  } catch (error) {
    console.error('Failed to track conversion:', error);
  }

  res.redirect('/thank-you');
});

Key Implementation Notes

✔️ Consistent User Identification: Uses createContext() to establish user identity.
✔️ Experiment Variant Handling: Uses runExperience() to determine the assigned pricing tier.
✔️ Error Handling: Ensures a fallback to standard pricing if the SDK fails.
✔️ Conversion Tracking: Uses trackConversion() to track subscriptions.

Example 2: Free Trial Length Experiment

Business Context

The growth team is testing whether extending the free trial period from 7 days to 14 days leads to higher conversion rates. The hypothesis is that a longer trial will allow users more time to see the product's value, ultimately increasing paid conversions.

Implementation

const Convert = require('@convertcom/js-sdk').default;
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

// Initialize SDK
const convert = new Convert({
  sdkKey: process.env.CONVERT_SDK_KEY,
  environment: 'production'
});

// Handle trial signup
async function handleTrialSignup(userId, email) {
  const experimentId = 'free_trial_length';

  try {
    const userContext = await convert.createContext({ userId });
    const result = await userContext.runExperience(experimentId);
    const variant = result.variationKey;
    const trialDays = variant === '14-day' ? 14 : 7;

    const customer = await stripe.customers.create({
      email: email,
      metadata: { userId, trialLength: trialDays }
    });

    const subscription = await stripe.subscriptions.create({
      customer: customer.id,
      items: [{ price: 'price_monthly_plan' }],
      trial_period_days: trialDays
    });

    await userContext.trackConversion('trial_started', {
      conversionData: [{
        experienceId: experimentId,
        variationId: result.variationId,
        trialDays: trialDays,
        subscriptionId: subscription.id
      }]
    });

    return {
      success: true,
      trialDays,
      subscriptionId: subscription.id
    };
  } catch (error) {
    console.error('Trial signup failed:', error);
    return handleFallbackTrialSignup(userId, email);
  }
}

// Example usage in signup route
app.post('/signup', async (req, res) => {
  const userId = generateUserId();
  const email = req.body.email;

  const result = await handleTrialSignup(userId, email);

  res.json({
    success: true,
    trialEnds: new Date(Date.now() + (result.trialDays * 86400000))
  });
});

Key Implementation Notes

✔️ Integrates Convert's SDK with Stripe for trial management
✔️ Uses runExperience() to get trial length variant
✔️ Tracks both trial start and conversion events
✔️ Implements fallback logic in case of errors

More Examples

  • Example 3: Payment Grace Period Workflow (Optimizing churn reduction with email vs. in-app notifications)
  • Example 4: Implementing Persistent Storage (Ensuring users consistently receive the same experiment variant)
  • Example 5: Analytics Integration (Syncing Convert's tracking with external analytics platforms)

Best Practices for Convert SDK Implementation

1. Error Handling & Fallbacks

Ensure robust error handling to maintain smooth user experiences:

try {
  // Convert SDK code
} catch (error) {
  console.error('Convert SDK error:', error);
  // Fallback implementation
}

2. Environment Configuration

Set the correct environment for production or staging:

const convert = new Convert({
  sdkKey: process.env.CONVERT_SDK_KEY,
  environment: 'production'
});

3. Consistent User Identification

Use a unique, stable user identifier to maintain experiment consistency:

const userContext = await convert.createContext({ userId: user.uniqueId });

4. Event Tracking Standards

Maintain structured event naming and data formats:

await userContext.trackConversion('purchase_completed', { 
  conversionData: [{ amount: orderTotal, transactionId: orderId }] 
});

Conclusion

These examples demonstrate how to effectively implement Convert's JavaScript SDK for A/B testing and feature flagging.

👉 Ensure proper experiment setup in the Convert dashboard before coding.
👉 Align experiment goals with business objectives.
👉 Follow best practices to ensure reliability and consistency.

For more details, visit the official Convert JavaScript SDK documentation. 🚀