Installation#

@pulsora/revenue is a server-side package for tracking revenue events with full attribution to customer journeys.

⚠️ Important: This package is for server-side use only. Never use it in the browser as it requires your secret API token.

Prerequisites#

  • Node.js 14 or higher
  • A Pulsora account with API access
  • Access to your payment webhook endpoints

NPM Installation#

1. Install the Package#

npm install @pulsora/revenue

Or using Yarn:

yarn add @pulsora/revenue

Or using pnpm:

pnpm add @pulsora/revenue

2. Import and Initialize#

// CommonJS
const { Revenue } = require('@pulsora/revenue');

// ES Modules
import { Revenue } from '@pulsora/revenue';

// Initialize with your secret API token
const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN,
});

3. TypeScript Support#

TypeScript definitions are included:

import { Revenue, RevenueConfig, RevenueData } from '@pulsora/revenue';

const config: RevenueConfig = {
  apiToken: process.env.PULSORA_SECRET_TOKEN!,
  debug: process.env.NODE_ENV === 'development',
};

const revenue = new Revenue(config);

Environment Setup#

1. Environment Variables#

Create a .env file in your project root:

# Production
PULSORA_SECRET_TOKEN=sec_your_secret_token_here

# Development
PULSORA_SECRET_TOKEN=sec_your_test_token_here
PULSORA_DEBUG=true

2. Load Environment Variables#

// Using dotenv
require('dotenv').config();

// Or in ES modules
import dotenv from 'dotenv';
dotenv.config();

// Initialize with env vars
const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN,
  debug: process.env.PULSORA_DEBUG === 'true',
});

Configuration Options#

interface RevenueConfig {
  apiToken: string; // Required: Your secret API token
  endpoint?: string; // Optional: Custom API endpoint
  debug?: boolean; // Optional: Enable debug logging
  maxRetries?: number; // Optional: Max retry attempts (default: 3)
  retryBackoff?: number; // Optional: Initial retry delay in ms (default: 1000)
}

Basic Configuration#

const revenue = new Revenue({
  apiToken: 'sec_your_secret_token',
});

Advanced Configuration#

const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN,
  endpoint: 'https://custom.pulsora.co/api/ingest',
  debug: true,
  maxRetries: 5,
  retryBackoff: 2000,
});

Framework Integration#

Express.js#

const express = require('express');
const { Revenue } = require('@pulsora/revenue');

const app = express();
const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN,
});

// Webhook endpoint
app.post('/webhooks/stripe', express.json(), async (req, res) => {
  const event = req.body;

  if (event.type === 'checkout.session.completed') {
    await revenue.track({
      visitor_fingerprint: event.data.object.metadata.visitor_fingerprint,
      session_id: event.data.object.metadata.session_id,
      customer_id: event.data.object.customer,
      amount: event.data.object.amount_total / 100,
      currency: event.data.object.currency,
      transaction_id: event.data.object.id,
      payment_processor: 'stripe',
      event_type: 'purchase',
    });
  }

  res.json({ received: true });
});

Next.js API Routes#

// pages/api/webhooks/stripe.ts (Pages Router)
// app/api/webhooks/stripe/route.ts (App Router)

import { NextRequest, NextResponse } from 'next/server';
import { Revenue } from '@pulsora/revenue';

const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN!,
});

export async function POST(request: NextRequest) {
  const event = await request.json();

  try {
    await revenue.track({
      // ... revenue data
    });

    return NextResponse.json({ success: true });
  } catch (error) {
    console.error('Revenue tracking error:', error);
    return NextResponse.json(
      { error: 'Failed to track revenue' },
      { status: 500 },
    );
  }
}

Fastify#

const fastify = require('fastify')();
const { Revenue } = require('@pulsora/revenue');

const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN,
});

fastify.post('/webhooks/paddle', async (request, reply) => {
  const event = request.body;

  if (event.event_type === 'transaction.completed') {
    await revenue.track({
      visitor_fingerprint: event.custom_data.visitor_fingerprint,
      session_id: event.custom_data.session_id,
      customer_id: event.customer_id,
      amount: parseFloat(event.amount),
      currency: event.currency_code,
      transaction_id: event.id,
      payment_processor: 'paddle',
      event_type: 'purchase',
    });
  }

  return { success: true };
});

AWS Lambda#

const { Revenue } = require('@pulsora/revenue');

const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN,
});

exports.handler = async (event) => {
  const body = JSON.parse(event.body);

  try {
    await revenue.track({
      visitor_fingerprint: body.metadata.visitor_fingerprint,
      session_id: body.metadata.session_id,
      customer_id: body.customer_id,
      amount: body.amount,
      currency: body.currency,
      transaction_id: body.transaction_id,
      payment_processor: 'custom',
      event_type: 'purchase',
    });

    return {
      statusCode: 200,
      body: JSON.stringify({ success: true }),
    };
  } catch (error) {
    console.error('Revenue tracking error:', error);
    return {
      statusCode: 500,
      body: JSON.stringify({ error: 'Failed to track revenue' }),
    };
  }
};

Vercel Edge Functions#

import { Revenue } from '@pulsora/revenue';

const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN!,
});

export const config = {
  runtime: 'edge',
};

export default async function handler(request: Request) {
  const event = await request.json();

  await revenue.track({
    // ... revenue data
  });

  return new Response(JSON.stringify({ success: true }), {
    status: 200,
    headers: { 'Content-Type': 'application/json' },
  });
}

Security Best Practices#

1. Never Expose Secret Tokens#

// ❌ WRONG - Never hardcode secret tokens
const revenue = new Revenue({
  apiToken: 'sec_abc123...',
});

// ✅ CORRECT - Use environment variables
const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN,
});

2. Validate Webhook Signatures#

Always verify webhook signatures from payment providers:

// Stripe example
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

app.post(
  '/webhooks/stripe',
  express.raw({ type: 'application/json' }),
  async (req, res) => {
    const sig = req.headers['stripe-signature'];

    try {
      // Verify webhook signature
      const event = stripe.webhooks.constructEvent(
        req.body,
        sig,
        process.env.STRIPE_WEBHOOK_SECRET,
      );

      // Now safe to process
      if (event.type === 'checkout.session.completed') {
        await revenue.track({
          // ... revenue data
        });
      }

      res.json({ received: true });
    } catch (err) {
      console.error('Webhook signature verification failed:', err);
      res.status(400).send(`Webhook Error: ${err.message}`);
    }
  },
);

3. Use HTTPS Only#

Ensure all webhook endpoints use HTTPS:

// Force HTTPS in production
if (process.env.NODE_ENV === 'production') {
  app.use((req, res, next) => {
    if (req.header('x-forwarded-proto') !== 'https') {
      res.redirect(`https://${req.header('host')}${req.url}`);
    } else {
      next();
    }
  });
}

Verification#

1. Test Installation#

// test-revenue.js
const { Revenue } = require('@pulsora/revenue');

const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN,
  debug: true,
});

// Test tracking
async function test() {
  try {
    await revenue.track({
      visitor_fingerprint: 'test_fp_123',
      session_id: 'test_session_123',
      customer_id: 'test_customer',
      amount: 9.99,
      currency: 'USD',
      transaction_id: 'test_tx_' + Date.now(),
      payment_processor: 'test',
      event_type: 'purchase',
    });

    console.log('✅ Revenue tracking successful');
  } catch (error) {
    console.error('❌ Revenue tracking failed:', error);
  }
}

test();

2. Debug Mode#

Enable debug mode to see detailed logs:

const revenue = new Revenue({
  apiToken: process.env.PULSORA_SECRET_TOKEN,
  debug: true,
});

// All API calls will be logged
// [Pulsora Revenue] Tracking revenue event...
// [Pulsora Revenue] Request: POST https://pulsora.co/api/ingest
// [Pulsora Revenue] Response: 200 OK

3. Check Dashboard#

After successful tracking:

  1. Log in to your Pulsora dashboard
  2. Navigate to Revenue Analytics
  3. Verify test events appear
  4. Check attribution data

Troubleshooting#

Common Issues#

"Invalid API token"

  • Ensure you're using a secret token (starts with sec_)
  • Check for typos or extra spaces
  • Verify token in Pulsora dashboard

"Module not found"

# Ensure package is installed
npm list @pulsora/revenue

# Reinstall if needed
npm install @pulsora/revenue

"Network error"

  • Check your server has internet access
  • Verify firewall allows outbound HTTPS
  • Test endpoint connectivity:
curl -X POST https://pulsora.co/api/ingest \
  -H "Authorization: Bearer your_token" \
  -H "Content-Type: application/json" \
  -d '{"test": true}'

Environment Checklist#

  • Secret API token in environment variables
  • Token starts with sec_
  • Package installed correctly
  • Server has internet access
  • Webhook endpoint accessible
  • Error handling implemented

Next Steps#

Now that you have the revenue package installed:

  1. Basic Usage - Track your first revenue event
  2. Webhook Integration - Set up payment webhooks
  3. Attribution - Understand visitor attribution
  4. API Reference - Complete method documentation

Need Help?#