npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@quickpipe/analytics-sdk

v1.0.0

Published

JavaScript/TypeScript SDK for sending analytics events to QuickPipe

Readme

QuickPipe Analytics API & SDK

Complete analytics tracking and PQL (Product Qualified Lead) scoring platform for SaaS applications.

📖 Interactive Documentation - Full docs with playgrounds, API reference, and SDK guides

QuickPipe provides two integration methods:

| Method | Best For | Languages | |--------|----------|-----------| | REST API | Direct HTTP calls, any language, server-side control | Any (cURL, Python, Ruby, Go, Java, etc.) | | SDK | Simplified integration, automatic batching, type safety | JavaScript/TypeScript, Python |

Core capabilities:

  1. Track events - Log user actions like sign-ups, feature usage, payments
  2. Score leads - Calculate a 0-100 PQL score to identify conversion-ready users
  3. Identify users - Associate events with user profiles and traits

Documentation

| Resource | Description | |----------|-------------| | Interactive Docs | Customer documentation with live playgrounds | | Getting Started | Overview and quick start | | API Reference | REST API endpoints and authentication | | SDK Documentation | JavaScript/TypeScript SDK reference | | API Playground | Test API endpoints in browser | | SDK Playground | Test SDK in browser | | PQL Calculator | Interactive scoring tool |


Table of Contents


Quick Start

Quick Start: REST API

No SDK required - just HTTP calls:

# Set your API key
export QUICKPIPE_API_KEY="qp_live_your_key_here"

# Track an event
curl -X POST https://api.quickpipe.ai/events/track \
  -H "Authorization: Bearer $QUICKPIPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-123",
    "event": "feature_used",
    "properties": {
      "feature": "dashboard",
      "eventTypes": "feature_used"
    }
  }'

# Identify a user
curl -X POST https://api.quickpipe.ai/users/identify \
  -H "Authorization: Bearer $QUICKPIPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-123",
    "traits": {
      "email": "[email protected]",
      "name": "Jane Doe",
      "company": "Acme Inc"
    }
  }'

# Calculate PQL score
curl -X POST https://api.quickpipe.ai/pql/calculate \
  -H "Authorization: Bearer $QUICKPIPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-123",
    "behavioral": { "featureUsageCount": 25, "sessionCount": 12 },
    "firmographic": { "companySize": 150, "hasPaymentMethod": true }
  }'

Quick Start: SDK

For JavaScript/TypeScript or Python applications with built-in batching and type safety:

import { createAnalytics, createPQLScorer, STANDARD_EVENTS } from '@quickpipe/analytics-sdk';

// 1. Track a user event
const analytics = createAnalytics({ apiKey: 'your-api-key' });
analytics.identify('user-123', { email: '[email protected]' });
analytics.track(STANDARD_EVENTS.FEATURE_USED, { eventTypes: 'search' });

// 2. Score a lead
const scorer = createPQLScorer();
const result = scorer.calculate({
  behavioral: { featureUsageCount: 25, sessionCount: 12 },
  engagement: { emailOpenRate: 0.45, lastActiveAt: new Date() },
  firmographic: { companySize: 150, hasPaymentMethod: true }
});

console.log(result.total);      // 73
console.log(result.category);   // 'warm'
console.log(result.recommendations); // ['Add to nurture sequence', ...]

Part 1: REST API

The QuickPipe REST API allows you to integrate analytics and PQL scoring from any programming language or platform. All you need is the ability to make HTTP requests.

Base URL: https://api.quickpipe.ai

Authentication

All API requests require authentication using your API key in the Authorization header:

Authorization: Bearer qp_live_your_key_here

API Key Types: | Key Prefix | Environment | Usage | |------------|-------------|-------| | qp_live_ | Production | Live customer data | | qp_test_ | Sandbox | Testing and development |

Track Events (API)

Endpoint: POST /events/track

Record a user action or event.

curl -X POST https://api.quickpipe.ai/events/track \
  -H "Authorization: Bearer $QUICKPIPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-123",
    "event": "feature_used",
    "properties": {
      "eventTypes": "feature_used",
      "feature": "advanced_search",
      "applicationId": "app-456"
    },
    "timestamp": "2024-01-15T10:30:00Z"
  }'

Request Body:

| Field | Type | Required | Description | |-------|------|----------|-------------| | userId | string | Yes | Unique user identifier | | event | string | Yes | Event name (use standard events) | | properties | object | No | Event metadata | | properties.eventTypes | string | Recommended | Event category for scoring | | timestamp | string | No | ISO 8601 timestamp (defaults to now) |

Response:

{
  "success": true,
  "eventId": "evt_abc123",
  "timestamp": "2024-01-15T10:30:00.000Z"
}

Identify Users (API)

Endpoint: POST /users/identify

Create or update a user profile with traits.

curl -X POST https://api.quickpipe.ai/users/identify \
  -H "Authorization: Bearer $QUICKPIPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-123",
    "traits": {
      "email": "[email protected]",
      "name": "Jane Doe",
      "company": "Acme Inc",
      "plan": "professional",
      "signupDate": "2024-01-01"
    }
  }'

Request Body:

| Field | Type | Required | Description | |-------|------|----------|-------------| | userId | string | Yes | Unique user identifier | | traits | object | No | User properties to store | | traits.email | string | Recommended | User email address | | traits.name | string | No | User display name | | traits.company | string | No | Company name | | traits.* | any | No | Custom user properties |

Response:

{
  "success": true,
  "userId": "user-123",
  "created": false,
  "updated": true
}

Calculate PQL Score (API)

Endpoint: POST /pql/calculate

Calculate a PQL score for a user based on their data.

curl -X POST https://api.quickpipe.ai/pql/calculate \
  -H "Authorization: Bearer $QUICKPIPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user-123",
    "behavioral": {
      "featureUsageCount": 25,
      "sessionCount": 12,
      "avgSessionDuration": 480,
      "keyFeaturesUsed": ["dashboard", "reports", "api"]
    },
    "engagement": {
      "emailOpenRate": 0.45,
      "lastActiveAt": "2024-01-15T10:30:00Z"
    },
    "firmographic": {
      "companySize": 150,
      "industry": "technology",
      "hasPaymentMethod": true,
      "isOnTrial": true,
      "trialDaysRemaining": 3
    }
  }'

Response:

{
  "total": 82,
  "category": "hot",
  "breakdown": {
    "behavioral": { "subtotal": 78, "weighted": 31.2 },
    "engagement": { "subtotal": 85, "weighted": 25.5 },
    "firmographic": { "subtotal": 84, "weighted": 25.2 }
  },
  "topFactors": [
    { "name": "trialUrgency", "contribution": 18 },
    { "name": "keyFeatureAdoption", "contribution": 15 }
  ],
  "recommendations": [
    "🔥 Schedule sales call immediately",
    "Trial ending soon - offer extension or discount"
  ],
  "calculatedAt": "2024-01-15T10:30:00.000Z"
}

API Error Handling

All errors return a consistent format:

{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "userId is required",
    "details": { "field": "userId" }
  }
}

Error Codes:

| Code | HTTP Status | Description | |------|-------------|-------------| | UNAUTHORIZED | 401 | Invalid or missing API key | | INVALID_REQUEST | 400 | Malformed request body | | NOT_FOUND | 404 | User or resource not found | | RATE_LIMITED | 429 | Too many requests | | INTERNAL_ERROR | 500 | Server error |

Rate Limits:

| Plan | Requests/minute | Events/day | |------|-----------------|------------| | Free | 60 | 10,000 | | Starter | 300 | 100,000 | | Professional | 1,000 | 1,000,000 | | Enterprise | Custom | Unlimited |


Part 2: SDK Installation

JavaScript/TypeScript SDK

npm install @quickpipe/analytics-sdk

Or with Yarn/pnpm:

yarn add @quickpipe/analytics-sdk
pnpm add @quickpipe/analytics-sdk

Python SDK

pip install quickpipe-analytics

Or with Poetry:

poetry add quickpipe-analytics

Part 3: Analytics Tracking

Track user actions to build a behavioral profile for scoring.

Setup

import { createAnalytics } from '@quickpipe/analytics-sdk';

const analytics = createAnalytics({
  apiKey: 'qp_test_quickpipe_demo',           // Required
  endpoint: 'http://localhost:8000', // Optional, this is the default
  flushInterval: 5000,              // Optional: batch flush interval (ms)
  flushAt: 10,                      // Optional: flush after N events
  debug: false,                     // Optional: enable console logs
  strictEvents: true                // Optional: throw on invalid events
});

Environment variables (alternative to config):

  • QUICKPIPE_ANALYTICS_API_KEY - Your API key
  • QUICKPIPE_ANALYTICS_ENDPOINT - Custom endpoint

Identify Users

Link events to a specific user:

// Basic
analytics.identify('user-123');

// With traits (stored and attached to events)
analytics.identify('user-123', {
  email: '[email protected]',
  name: 'Jane Doe',
  applicationId: 'app-456'
});

For anonymous users before sign-up:

analytics.setAnonymousId('anon-abc');

Track Events

import { STANDARD_EVENTS } from '@quickpipe/analytics-sdk';

// Using standard event names (recommended)
analytics.track(STANDARD_EVENTS.SIGN_UP, {
  eventTypes: 'sign_up',
  applicationId: 'app-456'
});

// Track a feature being used
analytics.track(STANDARD_EVENTS.FEATURE_USED, {
  eventTypes: 'search',
  feature: 'advanced_search',
  applicationId: 'app-456'
});

// Track a payment
analytics.track(STANDARD_EVENTS.PAYMENT_SUCCEEDED, {
  eventTypes: 'payment',
  amount: 99.00,
  currency: 'USD'
});

// Force send immediately (otherwise batched)
await analytics.flush();

Standard Events & Weights

Each event has a weight (0-10) that contributes to PQL scoring. Higher weight = stronger buying signal.

User Lifecycle

| Event | Weight | Constant | |-------|--------|----------| | Sign Up | 4 | SIGN_UP | | Sign In | 3 | SIGN_IN | | Sign Out | 1 | SIGN_OUT | | Account Created | 5 | ACCOUNT_CREATED | | Account Deleted | 0 | ACCOUNT_DELETED | | Password Reset | 2 | PASSWORD_RESET | | Password Changed | 2 | PASSWORD_CHANGED | | Email Verified | 5 | EMAIL_VERIFIED | | Invite Sent | 7 | INVITE_SENT | | Invite Accepted | 8 | INVITE_ACCEPTED | | Invite Declined | 0 | INVITE_DECLINED |

Payment & Billing

| Event | Weight | Constant | |-------|--------|----------| | Payment Succeeded | 10 | PAYMENT_SUCCEEDED | | Payment Failed | 0 | PAYMENT_FAILED | | Subscription Started | 9 | SUBSCRIPTION_STARTED | | Subscription Cancelled | 0 | SUBSCRIPTION_CANCELLED | | Subscription Changed | 5 | SUBSCRIPTION_CHANGED | | Subscription Renewed | 8 | SUBSCRIPTION_RENEWED | | Subscription Upgraded | 9 | SUBSCRIPTION_UPGRADED | | Subscription Downgraded | 2 | SUBSCRIPTION_DOWNGRADED | | Trial Started | 6 | TRIAL_STARTED | | Trial Ended | 3 | TRIAL_ENDED | | Invoice Created | 4 | INVOICE_CREATED | | Invoice Paid | 7 | INVOICE_PAID | | Refund Issued | 0 | REFUND_ISSUED |

Engagement & Product Usage

| Event | Weight | Constant | |-------|--------|----------| | Page View | 2 | PAGE_VIEW | | Feature Used | 6 | FEATURE_USED | | Search Performed | 4 | SEARCH_PERFORMED | | Document Viewed | 4 | DOCUMENT_VIEWED | | Document Created | 7 | DOCUMENT_CREATED | | Document Updated | 6 | DOCUMENT_UPDATED | | Document Deleted | 2 | DOCUMENT_DELETED | | Export Started | 5 | EXPORT_STARTED | | Export Completed | 7 | EXPORT_COMPLETED | | Import Started | 5 | IMPORT_STARTED | | Import Completed | 7 | IMPORT_COMPLETED |

Email & Communication

| Event | Weight | Constant | |-------|--------|----------| | Email Sent | 3 | EMAIL_SENT | | Email Opened | 4 | EMAIL_OPENED | | Email Clicked | 5 | EMAIL_CLICKED | | Email Bounced | 0 | EMAIL_BOUNCED | | Email Delivered | 3 | EMAIL_DELIVERED | | Email Unsubscribed | 0 | EMAIL_UNSUBSCRIBED |

Integrations

| Event | Weight | Constant | |-------|--------|----------| | Integration Connected | 8 | INTEGRATION_CONNECTED | | Integration Disconnected | 0 | INTEGRATION_DISCONNECTED | | API Called | 6 | API_CALLED |

Workspace & Team

| Event | Weight | Constant | |-------|--------|----------| | Workspace Created | 6 | WORKSPACE_CREATED | | Workspace Deleted | 0 | WORKSPACE_DELETED | | Member Added | 8 | MEMBER_ADDED | | Member Removed | 2 | MEMBER_REMOVED | | Role Changed | 4 | ROLE_CHANGED |

Support

| Event | Weight | Constant | |-------|--------|----------| | Support Ticket Created | 3 | SUPPORT_TICKET_CREATED | | Support Ticket Resolved | 5 | SUPPORT_TICKET_RESOLVED | | Feedback Submitted | 6 | FEEDBACK_SUBMITTED |

Errors & System

| Event | Weight | Constant | |-------|--------|----------| | Error Occurred | 0 | ERROR_OCCURRED |

Using Weights in Code

import { STANDARD_EVENTS, EVENT_WEIGHTS, getEventWeight } from '@quickpipe/analytics-sdk';

// Get weight for an event
const weight = getEventWeight('PAYMENT_SUCCEEDED'); // 10

// Access weights directly
const inviteWeight = EVENT_WEIGHTS.INVITE_ACCEPTED; // 8

Part 4: PQL Scoring

What is PQL?

PQL (Product Qualified Lead) answers one question: "Is this user likely to convert?"

Unlike traditional marketing-qualified leads (MQL) based on form fills and downloads, PQL uses actual product behavior to predict conversion.

Traditional MQL: "Downloaded whitepaper" → Maybe interested?
PQL:             "Used 5 features, logged in 12 times, trial ending in 3 days" → YES, call them!

Quick Example

import { createPQLScorer } from '@quickpipe/analytics-sdk';

const scorer = createPQLScorer();

const result = scorer.calculate({
  userId: 'user-123',
  behavioral: {
    featureUsageCount: 25,      // Used features 25 times
    sessionCount: 12,           // Logged in 12 times
    avgSessionDuration: 480,    // 8 minutes per session
    keyFeaturesUsed: ['dashboard', 'reports', 'api'],
    activationStepsCompleted: 4,
    totalActivationSteps: 5
  },
  engagement: {
    emailOpenRate: 0.45,        // Opens 45% of emails
    clickThroughRate: 0.08,     // Clicks 8% of links
    lastActiveAt: new Date(),   // Active today
    supportTicketsCreated: 1
  },
  firmographic: {
    companySize: 150,           // 150 employees
    industry: 'technology',
    hasPaymentMethod: true,     // Credit card on file!
    isOnTrial: true,
    trialDaysRemaining: 3,      // Trial ending soon!
    planType: 'professional'
  }
});

console.log(result);
// {
//   total: 82,
//   category: 'hot',
//   recommendations: ['🔥 Schedule sales call immediately', ...],
//   ...
// }

Understanding the Score

Score Categories

| Score | Category | Meaning | What to do | |-------|----------|---------|------------| | 80-100 | 🔥 Hot | Ready to buy | Call immediately | | 50-79 | 🟡 Warm | Interested, needs nurturing | Email campaign | | 20-49 | 🔵 Cold | Low engagement | Educational content | | 0-19 | ⚪ Unqualified | Not a fit | Monitor passively |

The Three Pillars

The score combines three categories of signals:

┌─────────────────────────────────────────────────────────────────┐
│                      FINAL SCORE (0-100)                        │
├───────────────────┬───────────────────┬─────────────────────────┤
│   BEHAVIORAL      │   ENGAGEMENT      │    FIRMOGRAPHIC         │
│     (40%)         │     (30%)         │      (30%)              │
├───────────────────┼───────────────────┼─────────────────────────┤
│ What they DO      │ How they RESPOND  │ WHO they are            │
│ • Feature usage   │ • Email opens     │ • Company size          │
│ • Session count   │ • Click rate      │ • Industry fit          │
│ • Time in app     │ • Recency         │ • Payment method        │
│ • Key features    │ • Support tickets │ • Trial status          │
│ • Onboarding      │ • Docs viewed     │ • Plan type             │
└───────────────────┴───────────────────┴─────────────────────────┘

How the Math Works

  1. Each signal gets a raw score (0-100)
  2. Multiply by signal weight within its category
  3. Sum to get category subtotal
  4. Multiply by category distribution (40/30/30)
  5. Add all categories = final score

Example:

Feature usage: 83 × 0.20 (weight) = 16.6
Session count: 60 × 0.15 = 9.0
...
Behavioral subtotal = 65

Behavioral contribution = 65 × 0.40 (distribution) = 26
Engagement contribution = 55 × 0.30 = 16.5
Firmographic contribution = 70 × 0.30 = 21

FINAL SCORE = 26 + 16.5 + 21 = 63.5 → "warm"

Input Data

Behavioral Data

interface BehavioralData {
  featureUsageCount?: number;     // Total feature interactions (0-30+ → 0-100)
  sessionCount?: number;          // Login sessions (0-20+ → 0-100)
  avgSessionDuration?: number;    // Seconds per session (0-600+ → 0-100)
  keyFeaturesUsed?: string[];     // Your "aha moment" features
  totalKeyFeatures?: number;      // How many key features exist (default: 5)
  activationStepsCompleted?: number;
  totalActivationSteps?: number;  // Default: 5
}

What counts as a "key feature"? Features that correlate with conversion. Examples:

  • dashboard - Saw the main value
  • invite_teammate - Team adoption signal
  • connect_integration - Deep product usage
  • export_report - Getting real value

Engagement Data

interface EngagementData {
  emailOpenRate?: number;         // 0.0-1.0 (e.g., 0.45 = 45%)
  clickThroughRate?: number;      // 0.0-1.0 (e.g., 0.05 = 5%)
  lastActiveAt?: Date | string;   // When they last logged in
  supportTicketsCreated?: number; // 0-2 is good, 5+ is concerning
  helpDocsViewed?: number;
  contentEngagements?: number;    // Webinars, blog posts, etc.
}

Important: lastActiveAt is crucial! A user who hasn't logged in for 2 weeks is going cold fast.

Firmographic Data

interface FirmographicData {
  companySize?: number;           // Employee count
  industry?: string;              // e.g., 'technology', 'healthcare'
  targetIndustries?: string[];    // Override default target industries
  hasPaymentMethod?: boolean;     // Credit card on file = strong signal!
  isOnTrial?: boolean;
  trialDaysRemaining?: number;    // Lower = more urgent
  planType?: 'free' | 'starter' | 'professional' | 'enterprise';
}

Company size scoring (default, mid-market focus):

  • 0-9 employees: 30%
  • 10-49: 60%
  • 50-500: 100% ← Sweet spot
  • 501-2000: 80%
  • 2000+: 60%

Score Output

interface PQLResult {
  total: number;           // 0-100 score
  category: 'hot' | 'warm' | 'cold' | 'unqualified';
  breakdown: {
    behavioral: { subtotal, weighted, featureUsage, sessionCount, ... },
    engagement: { subtotal, weighted, emailOpenRate, recency, ... },
    firmographic: { subtotal, weighted, companySize, industry, ... }
  };
  topFactors: [            // What's driving the score
    { name: 'keyFeatureAdoption', contribution: 28 },
    { name: 'recency', contribution: 24 },
    ...
  ];
  recommendations: string[];  // Suggested actions
  calculatedAt: string;       // ISO timestamp
}

Customizing Weights

Pre-built Weight Profiles

import {
  createPQLScorer,
  DEFAULT_WEIGHTS,      // Balanced (40% behavioral, 30% engagement, 30% firmographic)
  FREEMIUM_WEIGHTS,     // For freemium/PLG products
  ENTERPRISE_WEIGHTS    // For enterprise sales
} from '@quickpipe/analytics-sdk';

// For enterprise sales (firmographic matters more)
const enterpriseScorer = createPQLScorer({
  weights: ENTERPRISE_WEIGHTS,
  categoryDistribution: [0.3, 0.25, 0.45]  // Less behavioral, more firmographic
});

Custom Weights

const scorer = createPQLScorer({
  weights: {
    behavioral: {
      featureUsage: 25,        // These must sum to 100
      sessionCount: 20,
      sessionDuration: 15,
      keyFeatureAdoption: 25,
      activationCompletion: 15
    },
    engagement: {
      emailOpenRate: 10,
      clickThroughRate: 15,
      recency: 35,             // Make recency more important
      supportInteractions: 20,
      contentEngagement: 20
    },
    firmographic: {
      companySize: 30,         // Focus on company fit
      industry: 25,
      paymentMethod: 20,
      trialStatus: 15,
      planType: 10
    }
  },
  thresholds: {
    hot: 85,    // Raise the bar for "hot"
    warm: 55,
    cold: 25
  },
  categoryDistribution: [0.35, 0.35, 0.30]  // Must sum to 1.0
});

SDK Reference

Analytics SDK Methods

createAnalytics(config?)

Creates an analytics instance.

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | apiKey | string | Required | Your QuickPipe API key | | endpoint | string | https://api.quickpipe.ai | API endpoint | | flushInterval | number | 5000 | Batch send interval (ms) | | flushAt | number | 10 | Flush after N events | | debug | boolean | false | Enable console logs | | strictEvents | boolean | true | Throw on invalid event names |

analytics.identify(userId, traits?)

Associates subsequent events with a user.

| Parameter | Type | Description | |-----------|------|-------------| | userId | string | Unique user identifier | | traits | object | Optional user properties: email, name, applicationId, plus custom |

analytics.track(event, properties)

Records an event.

| Parameter | Type | Description | |-----------|------|-------------| | event | string | Event name from STANDARD_EVENTS | | properties.eventTypes | string \| string[] | Event type(s) | | properties.email | string | Optional email | | properties.applicationId | string | Optional app ID | | properties.date | string | ISO timestamp (defaults to now) | | properties.* | any | Custom properties |

analytics.setAnonymousId(id)

Sets an anonymous ID for unauthenticated users.

analytics.flush(): Promise<void>

Immediately sends all queued events.

analytics.reset()

Clears user identity and event queue.


PQL Scorer Methods

createPQLScorer(config?)

Creates a scorer instance.

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | weights | PQLWeights | DEFAULT_WEIGHTS | Signal weights | | thresholds | object | {hot:80, warm:50, cold:20} | Category boundaries | | customWeight | number | 0.1 | Multiplier for custom signals | | categoryDistribution | [n,n,n] | [0.4, 0.3, 0.3] | [behavioral, engagement, firmographic] |

scorer.calculate(input): PQLResult

Calculates the PQL score.

Input:

| Field | Type | Description | |-------|------|-------------| | userId | string | User identifier | | email | string | User email | | behavioral | BehavioralData | Product usage signals | | engagement | EngagementData | Communication signals | | firmographic | FirmographicData | Company/account signals | | custom | Record<string, number> | Custom signals (0-100 each) |

Output (PQLResult):

| Field | Type | Description | |-------|------|-------------| | total | number | Score 0-100 | | category | 'hot' \| 'warm' \| 'cold' \| 'unqualified' | Score category | | breakdown | object | Detailed scores per dimension | | topFactors | Array<{name, contribution}> | Top scoring factors | | recommendations | string[] | Suggested actions | | calculatedAt | string | ISO timestamp |

Weight Constants

| Constant | Use Case | |----------|----------| | DEFAULT_WEIGHTS | Balanced scoring (most common) | | FREEMIUM_WEIGHTS | PLG/freemium products - weights product usage higher | | ENTERPRISE_WEIGHTS | Enterprise sales - weights firmographic higher |


Examples

Real-World: Identifying Hot Leads

import { createPQLScorer } from '@quickpipe/analytics-sdk';

const scorer = createPQLScorer();

// Fetch your users from database
const users = await db.users.findMany();

const hotLeads = users
  .map(user => ({
    user,
    score: scorer.calculate({
      behavioral: {
        featureUsageCount: user.eventCount,
        sessionCount: user.sessionCount,
        keyFeaturesUsed: user.featuresUsed
      },
      engagement: {
        lastActiveAt: user.lastSeenAt,
        emailOpenRate: user.emailStats?.openRate
      },
      firmographic: {
        companySize: user.company?.size,
        hasPaymentMethod: user.hasPaymentMethod,
        isOnTrial: user.trialEndsAt > new Date(),
        trialDaysRemaining: daysUntil(user.trialEndsAt)
      }
    })
  }))
  .filter(({ score }) => score.category === 'hot')
  .sort((a, b) => b.score.total - a.score.total);

// These users should be contacted by sales
for (const { user, score } of hotLeads) {
  console.log(`${user.email}: ${score.total} - ${score.recommendations[0]}`);
}

Tracking + Scoring Together

import { createAnalytics, createPQLScorer, STANDARD_EVENTS } from '@quickpipe/analytics-sdk';

const analytics = createAnalytics({ apiKey: process.env.API_KEY });
const scorer = createPQLScorer();

// When a user performs an action
async function onFeatureUsed(userId: string, feature: string) {
  // Track the event
  analytics.identify(userId);
  analytics.track(STANDARD_EVENTS.FEATURE_USED, {
    eventTypes: 'feature_used',
    feature
  });

  // Re-calculate score (you'd fetch real data from your DB)
  const userData = await getUserData(userId);
  const score = scorer.calculate(userData);

  // If they crossed into "hot", notify sales
  if (score.category === 'hot') {
    analytics.track(STANDARD_EVENTS.PQL_THRESHOLD_REACHED, {
      eventTypes: 'pql_hot',
      score: score.total
    });
    await notifySalesTeam(userId, score);
  }
}

Daily Lead Scoring Job

import { createPQLScorer, STANDARD_EVENTS } from '@quickpipe/analytics-sdk';

const scorer = createPQLScorer();

async function dailyLeadScoringJob() {
  const users = await db.users.findMany({ where: { isActive: true } });
  
  const results = {
    hot: [] as string[],
    warm: [] as string[],
    cold: [] as string[],
    unqualified: [] as string[]
  };

  for (const user of users) {
    const score = scorer.calculate({
      behavioral: await getBehavioralData(user.id),
      engagement: await getEngagementData(user.id),
      firmographic: await getFirmographicData(user.id)
    });

    // Store score
    await db.pqlScores.upsert({
      where: { userId: user.id },
      create: { userId: user.id, score: score.total, category: score.category },
      update: { score: score.total, category: score.category, updatedAt: new Date() }
    });

    results[score.category].push(user.email);
  }

  console.log(`Scoring complete:
    Hot: ${results.hot.length}
    Warm: ${results.warm.length}
    Cold: ${results.cold.length}
    Unqualified: ${results.unqualified.length}
  `);

  // Send hot leads to sales team
  if (results.hot.length > 0) {
    await sendToSalesforce(results.hot);
  }
}

Python SDK

For Python applications (Django, Flask, FastAPI), use the Python SDK:

pip install quickpipe-analytics
import os
from quickpipe import QuickPipeClient, PQLScorer, StandardEvents

# Initialize
client = QuickPipeClient(
    api_key=os.environ['QUICKPIPE_API_KEY'],
    endpoint='https://api.quickpipe.ai'
)

# Identify user
client.identify('user-123', {
    'email': '[email protected]',
    'name': 'Jane Doe'
})

# Track events
client.track('user-123', StandardEvents.FEATURE_USED, {
    'feature': 'dashboard'
})

# Calculate PQL score
scorer = PQLScorer()
result = scorer.calculate({
    'behavioral': {'featureUsageCount': 25, 'sessionCount': 12},
    'firmographic': {'companySize': 150, 'hasPaymentMethod': True}
})

print(result['total'])     # 73
print(result['category'])  # 'warm'

Project Structure

sdk/
├── docs/
│   ├── index.html      # Interactive documentation
│   ├── logo.png
│   └── favicon.png
├── src/
│   ├── client.ts       # Analytics client
│   ├── events.ts       # Standard events
│   ├── pql.ts          # PQL scorer
│   ├── types.ts        # TypeScript types
│   └── index.ts        # Main exports
├── examples/           # Example code
├── package.json
├── tsconfig.json
├── README.md
└── index.md

License

MIT


Internal: Developer Implementation Guide

⚠️ This section is for QuickPipe developers setting up the platform, NOT for customers using the SDK.

Architecture Overview

QuickPipe follows a simple data flow:

1. SDK (Input)      → Tracks user events in customer's frontend/backend
2. API (Processing) → Receives, validates, and stores events
3. Database         → Persists events and user data
4. PQL Scoring      → Calculates lead scores from aggregated data

Database Setup (PostgreSQL)

-- Users table
CREATE TABLE users (
    id VARCHAR(255) PRIMARY KEY,
    email VARCHAR(255),
    name VARCHAR(255),
    company VARCHAR(255),
    traits JSONB DEFAULT '{}',
    pql_score INTEGER DEFAULT 0,
    pql_category VARCHAR(20) DEFAULT 'unqualified',
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

-- Events table
CREATE TABLE events (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id VARCHAR(255) REFERENCES users(id),
    event_name VARCHAR(255) NOT NULL,
    properties JSONB DEFAULT '{}',
    timestamp TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_user_events ON events(user_id, timestamp);

-- PQL Scores history
CREATE TABLE pql_scores (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id VARCHAR(255) REFERENCES users(id),
    score INTEGER NOT NULL,
    category VARCHAR(20) NOT NULL,
    breakdown JSONB NOT NULL,
    calculated_at TIMESTAMP DEFAULT NOW()
);

Backend API Setup (Node.js/Express)

import express from 'express';
import { createPQLScorer } from '@quickpipe/analytics-sdk';
import { Pool } from 'pg';

const app = express();
const db = new Pool({ connectionString: process.env.DATABASE_URL });
const scorer = createPQLScorer();

app.use(express.json());

// Track event endpoint
app.post('/api/events/track', async (req, res) => {
    const { event, userId, properties } = req.body;
    await db.query(
        'INSERT INTO events (user_id, event_name, properties) VALUES ($1, $2, $3)',
        [userId, event, properties]
    );
    res.json({ success: true, eventId: crypto.randomUUID() });
});

// Calculate PQL score endpoint
app.post('/api/pql/score', async (req, res) => {
    const { userId } = req.body;
    const userData = await getUserMetrics(userId);
    const result = scorer.calculate(userData);
    await db.query(
        'UPDATE users SET pql_score = $1, pql_category = $2 WHERE id = $3',
        [result.total, result.category, userId]
    );
    res.json(result);
});

app.listen(3000);

Backend API Setup (Python/FastAPI)

from fastapi import FastAPI
from quickpipe import PQLScorer
import databases
import os

app = FastAPI()
db = databases.Database(os.environ['DATABASE_URL'])
scorer = PQLScorer()

@app.post("/api/events/track")
async def track_event(event: str, user_id: str, properties: dict = {}):
    await db.execute(
        "INSERT INTO events (user_id, event_name, properties) VALUES (:uid, :event, :props)",
        {"uid": user_id, "event": event, "props": properties}
    )
    return {"success": True}

@app.post("/api/pql/score")
async def calculate_score(user_id: str):
    metrics = await get_user_metrics(user_id)
    result = scorer.calculate(metrics)
    await db.execute(
        "UPDATE users SET pql_score = :score, pql_category = :cat WHERE id = :uid",
        {"score": result["total"], "cat": result["category"], "uid": user_id}
    )
    return result

Environment Variables

# .env
DATABASE_URL=postgresql://user:password@localhost:5432/quickpipe
QUICKPIPE_API_KEY=qp_live_xxx
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/xxx  # Optional: for hot lead alerts

Deployment Checklist

  • [ ] Set up PostgreSQL database
  • [ ] Run database migrations (see SQL above)
  • [ ] Configure environment variables
  • [ ] Deploy API server (Node.js or Python)
  • [ ] Generate API keys for customers
  • [ ] Set up cron job for daily PQL scoring
  • [ ] Configure Slack/CRM webhooks for hot lead alerts