JavaScript SDK

Das offizielle JavaScript SDK bietet eine komfortable Moeglichkeit, mit der Brevo API aus Ihren Node.js-Anwendungen und Browser-Umgebungen zu interagieren.

Installation

Terminal window
# Mit npm
npm install @brevo/brevo-js
# Mit yarn
yarn add @brevo/brevo-js
# Mit pnpm
pnpm add @brevo/brevo-js

Schnellstart

SDK initialisieren

import { ApiClient, TransactionalEmailsApi, ContactsApi, EventsApi } from '@brevo/brevo-js';
// API-Client konfigurieren
const defaultClient = ApiClient.instance;
const apiKey = defaultClient.authentications['api-key'];
apiKey.apiKey = 'your-brevo-api-key';
// API-Instanzen initialisieren
const emailApi = new TransactionalEmailsApi();
const contactsApi = new ContactsApi();
const eventsApi = new EventsApi();

Umgebungskonfiguration

.env-Datei
BREVO_API_KEY=xkeysib-your-api-key-here
BREVO_API_URL=https://api.brevo.com/v3
TAJO_WEBHOOK_SECRET=your-webhook-secret
// config.js
export const brevoConfig = {
apiKey: process.env.BREVO_API_KEY,
apiUrl: process.env.BREVO_API_URL || 'https://api.brevo.com/v3',
webhookSecret: process.env.TAJO_WEBHOOK_SECRET
};

Kernfunktionen

1. Kundenverwaltung

class TajoCustomerService {
constructor() {
this.contactsApi = new ContactsApi();
}
// Neuen Treuekunden erstellen
async createCustomer(customerData) {
const createContact = {
email: customerData.email,
attributes: {
FIRSTNAME: customerData.firstName,
LASTNAME: customerData.lastName,
PHONE: customerData.phone,
LOYALTY_ID: customerData.loyaltyId,
LOYALTY_POINTS: customerData.points || 0,
LOYALTY_TIER: customerData.tier || 'Bronze',
SIGNUP_DATE: new Date().toISOString(),
TOTAL_SPENT: customerData.totalSpent || 0,
PREFERRED_CATEGORIES: customerData.categories || [],
BIRTHDAY: customerData.birthday,
MARKETING_CONSENT: customerData.marketingConsent || true
},
listIds: [this.getListForTier(customerData.tier || 'Bronze')],
updateEnabled: true
};
try {
const response = await this.contactsApi.createContact(createContact);
console.log('Customer created in Brevo:', response.id);
return response;
} catch (error) {
console.error('Error creating customer:', error);
throw error;
}
}
// Kundentreue-Daten aktualisieren
async updateCustomer(email, updates) {
const updateContact = {
attributes: updates,
listIds: updates.LOYALTY_TIER ? [this.getListForTier(updates.LOYALTY_TIER)] : undefined
};
try {
await this.contactsApi.updateContact(email, updateContact);
console.log('Customer updated:', email);
} catch (error) {
console.error('Error updating customer:', error);
throw error;
}
}
// Kunde per E-Mail abrufen
async getCustomer(email) {
try {
const response = await this.contactsApi.getContactInfo(email);
return response;
} catch (error) {
if (error.status === 404) {
return null; // Kunde nicht gefunden
}
throw error;
}
}
// Hilfsmethode fuer Listen-ID pro Stufe
getListForTier(tier) {
const tierLists = {
'Bronze': 1,
'Silver': 2,
'Gold': 3,
'Platinum': 4
};
return tierLists[tier] || 1;
}
}

2. Transaktionale E-Mails

class TajoEmailService {
constructor() {
this.emailApi = new TransactionalEmailsApi();
}
// Benachrichtigung ueber gesammelte Treuepunkte senden
async sendPointsEarnedEmail(customerEmail, orderData) {
const sendSmtpEmail = {
sender: {
name: "Tajo Loyalty",
},
to: [{
email: customerEmail,
name: orderData.customerName
}],
subject: `Sie haben ${orderData.pointsEarned} Treuepunkte gesammelt!`,
htmlContent: this.generatePointsEmailHTML(orderData),
textContent: this.generatePointsEmailText(orderData),
params: {
customerName: orderData.customerName,
pointsEarned: orderData.pointsEarned,
orderNumber: orderData.orderNumber,
totalPoints: orderData.totalPoints
},
tags: ['loyalty', 'points-earned']
};
try {
const response = await this.emailApi.sendTransacEmail(sendSmtpEmail);
return response;
} catch (error) {
console.error('Error sending points email:', error);
throw error;
}
}
// Benachrichtigung ueber Stufen-Upgrade senden
async sendTierUpgradeEmail(customerEmail, upgradeData) {
const sendSmtpEmail = {
templateId: this.getTierUpgradeTemplateId(upgradeData.newTier),
to: [{ email: customerEmail }],
params: {
customerName: upgradeData.customerName,
newTier: upgradeData.newTier,
previousTier: upgradeData.previousTier,
benefits: upgradeData.benefits,
pointsBalance: upgradeData.pointsBalance
},
tags: ['loyalty', 'tier-upgrade', upgradeData.newTier.toLowerCase()]
};
return await this.emailApi.sendTransacEmail(sendSmtpEmail);
}
// HTML-Inhalt fuer Punkte-E-Mail generieren
generatePointsEmailHTML(orderData) {
return `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h1 style="color: #2c5aa0;">Tolle Neuigkeiten, ${orderData.customerName}!</h1>
<p>Sie haben <strong>${orderData.pointsEarned} Punkte</strong> durch Ihren letzten Einkauf gesammelt!</p>
<div style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin: 20px 0;">
<h3>Bestelldetails:</h3>
<p><strong>Bestellnummer:</strong> ${orderData.orderNumber}</p>
<p><strong>Gesammelte Punkte:</strong> ${orderData.pointsEarned}</p>
<p><strong>Gesamtpunkte:</strong> ${orderData.totalPoints}</p>
</div>
<p style="margin-top: 30px;">
<a href="https://yourdomain.com/loyalty/rewards"
style="background: #2c5aa0; color: white; padding: 12px 24px; text-decoration: none; border-radius: 4px;">
Praemien ansehen
</a>
</p>
</div>
`;
}
generatePointsEmailText(orderData) {
return `
Tolle Neuigkeiten, ${orderData.customerName}!
Sie haben ${orderData.pointsEarned} Punkte durch Ihren letzten Einkauf gesammelt!
Bestelldetails:
- Bestellnummer: ${orderData.orderNumber}
- Gesammelte Punkte: ${orderData.pointsEarned}
- Gesamtpunkte: ${orderData.totalPoints}
Praemien ansehen: https://yourdomain.com/loyalty/rewards
`;
}
}

3. Event-Tracking

class TajoEventTracker {
constructor() {
this.eventsApi = new EventsApi();
}
// Treue-Events verfolgen
async trackLoyaltyEvent(customerEmail, eventType, properties = {}) {
const createEvent = {
email: customerEmail,
event: eventType,
properties: {
timestamp: new Date().toISOString(),
platform: 'tajo',
...properties
}
};
try {
const response = await this.eventsApi.createEvent(createEvent);
return response;
} catch (error) {
console.error(`Error tracking event ${eventType}:`, error);
throw error;
}
}
// Spezifische Event-Tracking-Methoden
async trackPurchase(customerEmail, purchaseData) {
return this.trackLoyaltyEvent(customerEmail, 'Purchase Completed', {
order_id: purchaseData.orderId,
order_total: purchaseData.total,
currency: purchaseData.currency,
items_count: purchaseData.itemsCount,
points_earned: purchaseData.pointsEarned,
loyalty_tier: purchaseData.customerTier,
categories: purchaseData.categories
});
}
async trackPointsRedemption(customerEmail, redemptionData) {
return this.trackLoyaltyEvent(customerEmail, 'Points Redeemed', {
points_used: redemptionData.pointsUsed,
reward_type: redemptionData.rewardType,
reward_value: redemptionData.rewardValue,
remaining_points: redemptionData.remainingPoints,
redemption_method: redemptionData.method
});
}
async trackTierUpgrade(customerEmail, upgradeData) {
return this.trackLoyaltyEvent(customerEmail, 'Tier Upgraded', {
previous_tier: upgradeData.previousTier,
new_tier: upgradeData.newTier,
points_required: upgradeData.pointsRequired,
benefits_unlocked: upgradeData.benefitsUnlocked
});
}
async trackReferral(customerEmail, referralData) {
return this.trackLoyaltyEvent(customerEmail, 'Referral Made', {
referral_method: referralData.method,
referee_email: referralData.refereeEmail,
referral_bonus: referralData.bonus,
referral_code: referralData.code
});
}
}

Erweiterte Nutzung

1. Massenoperationen

class TajoBulkService {
constructor() {
this.contactsApi = new ContactsApi();
this.batchSize = 50; // Empfohlene Batch-Groesse
}
// Massenimport von Kunden
async importCustomers(customers) {
const batches = this.createBatches(customers, this.batchSize);
const results = [];
for (const batch of batches) {
try {
const contacts = batch.map(customer => ({
email: customer.email,
attributes: {
FIRSTNAME: customer.firstName,
LASTNAME: customer.lastName,
LOYALTY_POINTS: customer.points,
LOYALTY_TIER: customer.tier,
TOTAL_SPENT: customer.totalSpent
}
}));
const response = await this.contactsApi.importContacts({
contacts,
listIds: [1], // Standardliste
updateEnabled: true
});
results.push(response);
} catch (error) {
console.error('Batch import error:', error);
// Mit anderen Batches fortfahren
}
}
return results;
}
createBatches(array, batchSize) {
const batches = [];
for (let i = 0; i < array.length; i += batchSize) {
batches.push(array.slice(i, i + batchSize));
}
return batches;
}
}

2. Fehlerbehandlung und Wiederholungslogik

class TajoApiClient {
constructor() {
this.maxRetries = 3;
this.retryDelay = 1000; // 1 Sekunde
}
async apiCallWithRetry(apiCall, retries = this.maxRetries) {
try {
return await apiCall();
} catch (error) {
if (retries > 0 && this.isRetryableError(error)) {
console.log(`Retrying API call. Attempts remaining: ${retries - 1}`);
await this.delay(this.retryDelay);
return this.apiCallWithRetry(apiCall, retries - 1);
}
throw error;
}
}
isRetryableError(error) {
// Bei Ratenlimits, Serverfehlern und Netzwerkproblemen wiederholen
return error.status >= 500 || error.status === 429 || error.code === 'NETWORK_ERROR';
}
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}

3. Webhook-Verarbeitung

import express from 'express';
import crypto from 'crypto';
const app = express();
// Webhook-Endpunkt fuer Brevo-Events
app.post('/webhooks/brevo', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-brevo-signature'];
const payload = req.body;
// Webhook-Signatur ueberpruefen
if (!verifyWebhookSignature(payload, signature)) {
return res.status(401).json({ error: 'Invalid signature' });
}
const event = JSON.parse(payload);
switch (event.event) {
case 'delivered':
handleEmailDelivered(event);
break;
case 'opened':
handleEmailOpened(event);
break;
case 'clicked':
handleEmailClicked(event);
break;
case 'bounced':
handleEmailBounced(event);
break;
default:
console.log('Unhandled event type:', event.event);
}
res.status(200).json({ success: true });
});
function verifyWebhookSignature(payload, signature) {
const expectedSignature = crypto
.createHmac('sha256', process.env.TAJO_WEBHOOK_SECRET)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}
async function handleEmailOpened(event) {
// Kunden-Engagement-Score aktualisieren
const customerEmail = event.email;
const campaignType = event.tags?.includes('loyalty') ? 'loyalty' : 'general';
// Engagement in Ihrem System verfolgen
await updateCustomerEngagement(customerEmail, 'email_opened', {
campaign_type: campaignType,
subject: event.subject,
timestamp: event.ts
});
}

Tests

Unit-Tests

import { jest } from '@jest/globals';
import { TajoCustomerService } from '../src/customer-service.js';
describe('TajoCustomerService', () => {
let customerService;
let mockContactsApi;
beforeEach(() => {
mockContactsApi = {
createContact: jest.fn(),
updateContact: jest.fn(),
getContactInfo: jest.fn()
};
customerService = new TajoCustomerService();
customerService.contactsApi = mockContactsApi;
});
test('should create customer successfully', async () => {
const customerData = {
firstName: 'John',
lastName: 'Doe',
loyaltyId: 'LYL-001',
tier: 'Bronze'
};
mockContactsApi.createContact.mockResolvedValue({ id: 123 });
const result = await customerService.createCustomer(customerData);
expect(mockContactsApi.createContact).toHaveBeenCalledWith({
attributes: expect.objectContaining({
FIRSTNAME: 'John',
LASTNAME: 'Doe',
LOYALTY_ID: 'LYL-001',
LOYALTY_TIER: 'Bronze'
}),
listIds: [1],
updateEnabled: true
});
expect(result.id).toBe(123);
});
});

Integrationstests

describe('Brevo Integration Tests', () => {
let customerService;
beforeAll(() => {
customerService = new TajoCustomerService();
});
test('should sync customer to Brevo', async () => {
const testCustomer = {
email: `test-${Date.now()}@example.com`,
firstName: 'Test',
lastName: 'User',
loyaltyId: `LYL-${Date.now()}`,
tier: 'Bronze',
points: 100
};
// Kunde erstellen
const createResult = await customerService.createCustomer(testCustomer);
expect(createResult.id).toBeDefined();
// Kunde ueberpruefen
const retrievedCustomer = await customerService.getCustomer(testCustomer.email);
expect(retrievedCustomer.email).toBe(testCustomer.email);
expect(retrievedCustomer.attributes.LOYALTY_POINTS).toBe(100);
// Aufraeumen
await customerService.deleteCustomer(testCustomer.email);
});
});

Leistungsoptimierung

Caching

import Redis from 'ioredis';
class TajoCachedService extends TajoCustomerService {
constructor() {
super();
this.redis = new Redis(process.env.REDIS_URL);
this.cacheTTL = 300; // 5 Minuten
}
async getCustomer(email) {
const cacheKey = `customer:${email}`;
// Zuerst Cache pruefen
const cached = await this.redis.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
// Von API abrufen
const customer = await super.getCustomer(email);
// Ergebnis cachen
if (customer) {
await this.redis.setex(cacheKey, this.cacheTTL, JSON.stringify(customer));
}
return customer;
}
}

Ratenbegrenzung

import { RateLimiter } from 'limiter';
class TajoRateLimitedService extends TajoCustomerService {
constructor() {
super();
// Brevo API Limits: 300 Aufrufe pro Minute
this.limiter = new RateLimiter({
tokensPerInterval: 300,
interval: 'minute'
});
}
async makeApiCall(apiCall) {
await this.limiter.removeTokens(1);
return apiCall();
}
async createCustomer(customerData) {
return this.makeApiCall(() => super.createCustomer(customerData));
}
}

Naechste Schritte

AI-Assistent

Hallo! Fragen Sie mich alles über die Dokumentation.

Kostenlos mit Brevo starten