savedemails
Version:
Simple email collection for your applications
328 lines (270 loc) • 7.48 kB
Markdown
# savedemails
Simple email collection SDK for your applications.
## Installation
```bash
npm install savedemails
# or
yarn add savedemails
# or
pnpm add savedemails
```
## Quick Start
```javascript
import { saveEmail } from "savedemails";
// Simple usage
const result = await saveEmail("user@example.com", "your-api-key");
// With additional data
const result = await saveEmail("user@example.com", "your-api-key", {
source: "landing-page",
metadata: {
plan: "pro",
referrer: "google",
},
});
```
## Configuration
The `saveEmail` function accepts an optional configuration object:
```javascript
const result = await saveEmail("user@example.com", "your-api-key", {
source: "newsletter-signup", // Optional: source identifier
metadata: {
/* custom data */
}, // Optional: additional metadata
baseUrl: "https://your-custom-domain.com", // Optional: custom API endpoint
});
```
## API Reference
### `saveEmail(email, apiKey, options?)`
Saves an email to your account.
#### Parameters
- `email` (string, required): The email address to save
- `apiKey` (string, required): Your API key for authentication
- `options` (object, optional): Configuration options
- `source` (string, optional): Source of the email (e.g., 'landing-page', 'signup-form')
- `metadata` (object, optional): Additional metadata to store with the email
- `baseUrl` (string, optional): Custom API endpoint (defaults to "https://savedemails.com")
#### Returns
Promise<{ success: boolean; id?: string; error?: string }> - Response object containing:
- `success` (boolean): Whether the email was saved successfully
- `id` (string, optional): The ID of the saved email (if successful)
- `error` (string, optional): Error message (if failed)
#### Examples
```javascript
// Simple email collection
try {
const result = await saveEmail("user@example.com", "your-api-key");
console.log("Email saved:", result);
} catch (error) {
console.error("Failed to save email:", error);
}
// With metadata
try {
const result = await saveEmail("user@example.com", "your-api-key", {
source: "newsletter-popup",
metadata: {
utm_source: "facebook",
utm_campaign: "summer-sale",
interests: ["tech", "startups"],
},
});
console.log("Email saved with metadata:", result);
} catch (error) {
console.error("Failed to save email:", error);
}
// With custom base URL
try {
const result = await saveEmail("user@example.com", "your-api-key", {
source: "beta-waitlist",
baseUrl: "https://your-custom-domain.com",
});
console.log("Email saved:", result);
} catch (error) {
console.error("Failed to save email:", error);
}
```
## Framework Examples
### React
```jsx
import { useState } from "react";
import { saveEmail } from "savedemails";
function NewsletterForm() {
const [email, setEmail] = useState("");
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState("");
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
const result = await saveEmail(email, process.env.REACT_APP_API_KEY, {
source: "newsletter-form",
metadata: {
page: window.location.pathname,
},
});
if (result.success) {
setMessage("Thanks for subscribing!");
setEmail("");
} else {
setMessage(result.error || "Something went wrong. Please try again.");
}
} catch (error) {
setMessage("Something went wrong. Please try again.");
} finally {
setLoading(false);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Enter your email"
required
/>
<button type="submit" disabled={loading}>
{loading ? "Subscribing..." : "Subscribe"}
</button>
{message && <p>{message}</p>}
</form>
);
}
```
### Vue 3
```vue
<template>
<form @submit.prevent="handleSubmit">
<input
v-model="email"
type="email"
placeholder="Enter your email"
required
/>
<button :disabled="loading">
{{ loading ? "Subscribing..." : "Subscribe" }}
</button>
<p v-if="message">{{ message }}</p>
</form>
</template>
<script setup>
import { ref } from "vue";
import { saveEmail } from "savedemails";
const email = ref("");
const loading = ref(false);
const message = ref("");
async function handleSubmit() {
loading.value = true;
try {
const result = await saveEmail(email.value, import.meta.env.VITE_API_KEY, {
source: "vue-app",
});
if (result.success) {
message.value = "Thanks for subscribing!";
email.value = "";
} else {
message.value = result.error || "Something went wrong. Please try again.";
}
} catch (error) {
message.value = "Something went wrong. Please try again.";
} finally {
loading.value = false;
}
}
</script>
```
### Next.js
```jsx
"use client";
import { useState } from "react";
import { saveEmail } from "savedemails";
export default function WaitlistForm() {
const [email, setEmail] = useState("");
const [status, setStatus] = useState("idle");
async function handleSubmit(e) {
e.preventDefault();
setStatus("loading");
try {
const result = await saveEmail(email, process.env.NEXT_PUBLIC_API_KEY, {
source: "waitlist",
metadata: {
timestamp: new Date().toISOString(),
},
});
if (result.success) {
setStatus("success");
setEmail("");
} else {
setStatus("error");
}
} catch (error) {
setStatus("error");
}
}
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="Join the waitlist"
required
disabled={status === "loading"}
/>
<button type="submit" disabled={status === "loading"}>
{status === "loading" ? "Joining..." : "Join Waitlist"}
</button>
{status === "success" && <p>You're on the list!</p>}
{status === "error" && <p>Something went wrong. Please try again.</p>}
</form>
);
}
```
## Error Handling
The SDK returns error information in the response object and throws errors for validation issues:
```javascript
try {
const result = await saveEmail("invalid-email", "your-api-key");
if (!result.success) {
console.error("Failed to save email:", result.error);
// Handle API errors
}
} catch (error) {
if (error.message === "Invalid email format") {
// Handle invalid email format
} else if (error.message === "API key is required") {
// Handle missing API key
} else if (error.message === "Email is required") {
// Handle missing email
} else {
// Handle other errors
}
}
```
## TypeScript Support
The SDK is written in TypeScript and provides full type definitions:
```typescript
import { saveEmail } from "savedemails";
interface SaveEmailOptions {
source?: string;
metadata?: Record<string, any>;
baseUrl?: string;
}
interface SaveEmailResponse {
success: boolean;
id?: string;
error?: string;
}
const result: SaveEmailResponse = await saveEmail(
"user@example.com",
"your-api-key",
{
source: "typescript-app",
metadata: {
userId: 123,
premium: true,
},
}
);
```
## License
MIT