npm package: @signup-storm/sdk
Description: TypeScript SDK for Signup Storm API integration
Author: Applied Designs, LLC
Latest version: 1.0.0

# Signup Storm TypeScript SDK

[![npm version](https://badge.fury.io/js/@signup-samurai%2Fsdk.svg)](https://badge.fury.io/js/@signup-samurai%2Fsdk)
[![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)

A comprehensive TypeScript SDK for integrating Signup Storm email signup functionality into your applications and landing pages.

## Features

- 🚀 **Easy Integration** - Simple API for email signups and management
- 🎯 **Attribution Tracking** - Automatic UTM parameter capture
- 📱 **Browser Utilities** - Form integration and widget creation
- 🔒 **Type Safety** - Full TypeScript support with comprehensive types
- 🎨 **Customizable** - Flexible styling and behavior options
- 📊 **Event System** - Listen to signup events and responses
- 🌐 **Universal** - Works in browser and Node.js environments
- ⚡ **Lightweight** - Zero dependencies, small bundle size

## Installation

```bash
npm install @signup-storm/sdk
```

```bash
yarn add @signup-storm/sdk
```

```bash
pnpm add @signup-storm/sdk
```

## Quick Start

### Basic Usage

```typescript
import { SignupStorm } from '@signup-storm/sdk';

const client = new SignupStorm({
  apiKey: 'your-api-key',
  baseUrl: 'https://your-signup-samurai-instance.com'
});

// Subscribe an email
const response = await client.signup({
  email: 'user@example.com',
  list: 'newsletter',
  tags: ['landing-page', 'early-access']
});

console.log('Signup successful:', response);
```

### Browser Integration

```typescript
import { createBrowserClient } from '@signup-storm/sdk';

const { client, browser } = createBrowserClient({
  apiKey: 'your-api-key',
  baseUrl: 'https://your-signup-samurai-instance.com'
});

// Integrate with existing form
browser.integrateForm({
  form: '#signup-form',
  list: 'newsletter',
  onSuccess: (response) => {
    console.log('User subscribed:', response.email);
  },
  onError: (error) => {
    console.error('Signup failed:', error.message);
  }
});
```

## API Reference

### SignupStorm Client

#### Constructor

```typescript
new SignupStorm(config: SignupStormConfig)
```

**Config Options:**
- `apiKey` (string, required) - Your API key
- `baseUrl` (string, required) - Your Signup Storm instance URL
- `timeout` (number, optional) - Request timeout in milliseconds (default: 10000)
- `headers` (object, optional) - Custom headers to include with requests
- `debug` (boolean, optional) - Enable debug logging (default: false)

#### Methods

##### `signup(request: SignupRequest): Promise<SignupResponse>`

Subscribe an email address to a list.

```typescript
const response = await client.signup({
  email: 'user@example.com',
  list: 'newsletter',
  tags: ['blog', 'early-access'],
  utm: {
    source: 'twitter',
    medium: 'social',
    campaign: 'launch'
  },
  customFields: {
    firstName: 'John',
    company: 'Acme Corp'
  }
});
```

**SignupRequest Properties:**
- `email` (string, required) - Email address to subscribe
- `list` (string, optional) - List slug to subscribe to
- `tags` (string[], optional) - Tags to apply to the subscriber
- `utm` (UTMParameters, optional) - UTM parameters for attribution
- `pageUrl` (string, optional) - URL where signup occurred (auto-detected in browser)
- `referrer` (string, optional) - Referrer URL (auto-detected in browser)
- `customFields` (object, optional) - Custom fields to store with subscriber
- `ipAddress` (string, optional) - IP address (auto-detected if not provided)
- `userAgent` (string, optional) - User agent (auto-detected in browser)
- `consentTimestamp` (string, optional) - GDPR consent timestamp
- `gdprConsent` (boolean, optional) - GDPR consent status

##### `unsubscribe(request: UnsubscribeRequest): Promise<UnsubscribeResponse>`

Unsubscribe an email address from a list or globally.

```typescript
const response = await client.unsubscribe({
  email: 'user@example.com',
  list: 'newsletter', // Optional - omit for global unsubscribe
  reason: 'No longer interested'
});
```

##### `getSubscriberStatus(email: string): Promise<SubscriberStatus>`

Check the subscription status of an email address.

```typescript
const status = await client.getSubscriberStatus('user@example.com');
console.log('Status:', status.status); // 'subscribed', 'unsubscribed', etc.
console.log('Lists:', status.lists);
console.log('Tags:', status.tags);
```

#### Event System

Listen to SDK events:

```typescript
client.on('signup:success', (event) => {
  console.log('Signup successful:', event.data);
});

client.on('signup:error', (event) => {
  console.error('Signup failed:', event.data);
});

client.on('request:start', (event) => {
  console.log('Request started:', event.data.type);
});
```

**Available Events:**
- `signup:success` - Successful signup
- `signup:error` - Signup error
- `unsubscribe:success` - Successful unsubscribe
- `unsubscribe:error` - Unsubscribe error
- `request:start` - Request started
- `request:complete` - Request completed

### Browser Utilities

#### Form Integration

Integrate with existing HTML forms:

```typescript
const cleanup = browser.integrateForm({
  form: '#my-form', // Form selector or element
  emailField: 'email', // Email input name/selector (default: 'email')
  list: 'newsletter',
  tags: ['website'],
  customFields: {
    firstName: '[name="first_name"]',
    company: '[name="company"]'
  },
  onSuccess: (response) => {
    // Handle success
    showSuccessMessage('Thanks for subscribing!');
  },
  onError: (error) => {
    // Handle error
    showErrorMessage(error.message);
  },
  onLoading: (loading) => {
    // Handle loading state
    toggleLoadingSpinner(loading);
  },
  preventDefault: true, // Prevent default form submission
  showLoadingState: true, // Show loading on submit button
  disableFormDuringSubmission: true // Disable form during submission
});

// Call cleanup when done
cleanup();
```

#### Widget Creation

Create embedded signup widgets:

```typescript
const widget = browser.createWidget({
  container: '#signup-container',
  list: 'newsletter',
  tags: ['widget'],
  placeholder: 'Enter your email address',
  buttonText: 'Subscribe Now',
  successMessage: 'Thanks for subscribing!',
  cssClasses: {
    container: 'my-signup-widget',
    form: 'signup-form',
    input: 'email-input',
    button: 'subscribe-btn',
    success: 'success-message',
    error: 'error-message'
  },
  styles: {
    container: {
      padding: '20px',
      borderRadius: '8px',
      backgroundColor: '#f5f5f5'
    },
    input: {
      padding: '12px',
      fontSize: '16px',
      border: '1px solid #ddd',
      borderRadius: '4px'
    },
    button: {
      padding: '12px 24px',
      backgroundColor: '#007bff',
      color: 'white',
      border: 'none',
      borderRadius: '4px',
      cursor: 'pointer'
    }
  }
});
```

#### Auto-Capture

Automatically capture emails from forms on the page:

```typescript
const cleanup = browser.autoCapture({
  selector: 'input[type="email"]', // Email input selector
  lists: ['newsletter'], // Auto-subscribe to these lists
  tags: ['auto-capture'],
  onCapture: (email) => {
    console.log('Email captured:', email);
  }
});

// Call cleanup when done
cleanup();
```

## Utilities

### Email Validation

```typescript
import { validateEmail } from '@signup-storm/sdk';

if (validateEmail('user@example.com')) {
  console.log('Valid email');
}
```

### UTM Parameter Extraction

```typescript
import { extractUTMFromURL, extractUTMFromCurrentPage } from '@signup-storm/sdk';

// Extract from specific URL
const utm = extractUTMFromURL('https://example.com?utm_source=twitter&utm_medium=social');

// Extract from current page (browser only)
const currentUTM = extractUTMFromCurrentPage();
```

### Browser Detection

```typescript
import { isBrowser } from '@signup-storm/sdk';

if (isBrowser()) {
  // Browser-specific code
  console.log('Running in browser');
}
```

## Examples

### React Integration

```tsx
import React, { useEffect, useRef } from 'react';
import { createBrowserClient } from '@signup-storm/sdk';

const SignupForm: React.FC = () => {
  const formRef = useRef<HTMLFormElement>(null);
  const [message, setMessage] = useState('');
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    const { browser } = createBrowserClient({
      apiKey: process.env.REACT_APP_SIGNUP_SAMURAI_API_KEY!,
      baseUrl: process.env.REACT_APP_SIGNUP_SAMURAI_URL!
    });

    const cleanup = browser.integrateForm({
      form: formRef.current!,
      list: 'newsletter',
      onSuccess: () => {
        setMessage('Thanks for subscribing!');
        setLoading(false);
      },
      onError: (error) => {
        setMessage(error.message);
        setLoading(false);
      },
      onLoading: setLoading
    });

    return cleanup;
  }, []);

  return (
    <div>
      <form ref={formRef}>
        <input
          type="email"
          name="email"
          placeholder="Enter your email"
          required
        />
        <button type="submit" disabled={loading}>
          {loading ? 'Subscribing...' : 'Subscribe'}
        </button>
      </form>
      {message && <p>{message}</p>}
    </div>
  );
};
```

### Vue.js Integration

```vue
<template>
  <form ref="signupForm" @submit.prevent>
    <input
      type="email"
      name="email"
      placeholder="Enter your email"
      required
    />
    <button type="submit" :disabled="loading">
      {{ loading ? 'Subscribing...' : 'Subscribe' }}
    </button>
    <p v-if="message">{{ message }}</p>
  </form>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { createBrowserClient } from '@signup-storm/sdk';

const signupForm = ref<HTMLFormElement>();
const message = ref('');
const loading = ref(false);
let cleanup: (() => void) | null = null;

onMounted(() => {
  const { browser } = createBrowserClient({
    apiKey: import.meta.env.VITE_SIGNUP_SAMURAI_API_KEY,
    baseUrl: import.meta.env.VITE_SIGNUP_SAMURAI_URL
  });

  cleanup = browser.integrateForm({
    form: signupForm.value!,
    list: 'newsletter',
    onSuccess: () => {
      message.value = 'Thanks for subscribing!';
      loading.value = false;
    },
    onError: (error) => {
      message.value = error.message;
      loading.value = false;
    },
    onLoading: (isLoading) => {
      loading.value = isLoading;
    }
  });
});

onUnmounted(() => {
  cleanup?.();
});
</script>
```

### Node.js Server Usage

```typescript
import { SignupStorm } from '@signup-storm/sdk';

const client = new SignupStorm({
  apiKey: process.env.SIGNUP_SAMURAI_API_KEY!,
  baseUrl: process.env.SIGNUP_SAMURAI_URL!
});

// API endpoint for server-side signups
app.post('/api/signup', async (req, res) => {
  try {
    const { email, list, tags } = req.body;
    
    const response = await client.signup({
      email,
      list,
      tags,
      ipAddress: req.ip,
      userAgent: req.get('User-Agent'),
      pageUrl: req.get('Referer')
    });

    res.json({ success: true, data: response });
  } catch (error) {
    res.status(400).json({ 
      success: false, 
      error: error.message 
    });
  }
});
```

## Error Handling

The SDK throws `SignupStormError` for API-related errors:

```typescript
import { SignupStormError } from '@signup-storm/sdk';

try {
  await client.signup({ email: 'invalid-email' });
} catch (error) {
  if (error instanceof SignupStormError) {
    console.log('Error code:', error.code);
    console.log('HTTP status:', error.status);
    console.log('Message:', error.message);
    console.log('Details:', error.details);
  }
}
```

## TypeScript Support

The SDK is written in TypeScript and provides comprehensive type definitions:

```typescript
import type { 
  SignupRequest, 
  SignupResponse, 
  UTMParameters,
  SubscriberStatus 
} from '@signup-storm/sdk';

const request: SignupRequest = {
  email: 'user@example.com',
  list: 'newsletter',
  utm: {
    source: 'twitter',
    medium: 'social'
  }
};
```

## Contributing

We welcome contributions! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.

### Development Setup

```bash
# Clone the repository
git clone https://github.com/yourusername/signup-samurai.git
cd signup-samurai/packages/sdk

# Install dependencies
pnpm install

# Start development mode
pnpm dev

# Run tests
pnpm test

# Run linting
pnpm lint
```

### Publishing (Maintainers Only)

The SDK is published to npm as `@signup-storm/sdk`. To publish a new version:

```bash
# Using the publish script (recommended)
./scripts/publish.sh

# Or manually
pnpm version patch  # or minor/major
pnpm prepublishOnly  # runs tests, linting, and build
npm publish
```

The package follows semantic versioning and includes automated checks before publishing.

## License

This SDK is licensed under the MIT License. See [LICENSE](../../LICENSE) for details.

## Support

- **Documentation**: [https://docs.signup-samurai.com](https://docs.signup-samurai.com)
- **Issues**: [GitHub Issues](https://github.com/yourusername/signup-samurai/issues)
- **Discord**: [Join our community](https://discord.gg/signup-samurai)

---

Made with ❤️ by [Applied Designs, LLC](https://signup-samurai.com)