Installation
composer require driveop/klaviyo-bundle
Add to config/bundles.php:
return [
// ...
Driveop\KlaviyoBundle\KlaviyoBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console config:dump-reference Driveop\KlaviyoBundle\DependencyInjection\Configuration
Update config/packages/klaviyo.yaml with your Klaviyo API credentials:
klaviyo:
api_key: '%env(KLAVIYO_API_KEY)%'
private_app_id: '%env(KLAVIYO_PRIVATE_APP_ID)%'
First Use Case Trigger a profile track event for a user:
use Driveop\KlaviyoBundle\Service\KlaviyoClient;
class UserController
{
public function __construct(private KlaviyoClient $klaviyo)
{
}
public function trackUserAction(User $user)
{
$this->klaviyo->trackProfile($user->email, [
'properties' => [
'First Name' => $user->firstName,
'Last Name' => $user->lastName,
'Lifetime Value' => $user->lifetimeValue,
],
'events' => [
'Signed Up' => true,
],
]);
}
}
Event Tracking
Use trackProfile() for user actions (e.g., sign-up, purchases):
$this->klaviyo->trackProfile($email, [
'properties' => ['Custom Property' => $value],
'events' => ['Event Name' => true],
]);
List Management Add/remove users from Klaviyo lists:
// Add to list
$this->klaviyo->addToList($listId, [$user1Email, $user2Email]);
// Remove from list
$this->klaviyo->removeFromList($listId, [$userEmail]);
Segmentation Sync custom properties for segmentation:
$this->klaviyo->syncProperties($email, [
'Custom Property 1' => $value1,
'Custom Property 2' => $value2,
]);
Campaign Integration Trigger campaigns via API:
$this->klaviyo->triggerCampaign($campaignId, $email);
Dependency Injection
Inject KlaviyoClient into services/controllers where Klaviyo actions are needed.
Example:
public function __construct(private KlaviyoClient $klaviyo) {}
Environment Variables
Store KLAVIYO_API_KEY and KLAVIYO_PRIVATE_APP_ID in .env:
KLAVIYO_API_KEY=your_api_key_here
KLAVIYO_PRIVATE_APP_ID=your_private_app_id
Batch Processing
Use bulk methods (e.g., addToList()) for large datasets to reduce API calls:
$this->klaviyo->addToList($listId, array_keys($userEmails));
Error Handling Wrap Klaviyo calls in try-catch blocks to handle API failures gracefully:
try {
$this->klaviyo->trackProfile($email, $data);
} catch (\Exception $e) {
$this->logger->error('Klaviyo error: ' . $e->getMessage());
}
API Rate Limits Klaviyo enforces rate limits (e.g., 10 requests/second). Implement retries with exponential backoff:
use Symfony\Component\Stopwatch\Stopwatch;
$stopwatch = new Stopwatch();
$event = $stopwatch->start('klaviyo_request');
try {
$this->klaviyo->trackProfile($email, $data);
} catch (\Exception $e) {
if ($stopwatch->getEvent('klaviyo_request')->getDuration() < 1000) {
sleep(1); // Simple backoff
retry();
}
throw $e;
}
Profile Sync Delays Klaviyo may take up to 5 minutes to sync profile data. Avoid relying on real-time updates for critical logic.
List IDs
Ensure listId is correct (found in Klaviyo dashboard under "Lists"). Hardcoding IDs is fragile; fetch dynamically if possible:
$listId = $this->klaviyo->getListIdByName('Your List Name');
Data Validation Klaviyo rejects malformed payloads. Validate inputs before sending:
if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException('Invalid email');
}
Enable Debug Mode
Set debug: true in klaviyo.yaml to log API requests/responses:
klaviyo:
debug: true
Check Logs
API errors and responses are logged to var/log/dev.log (or prod.log in production).
Test with Sandbox Use Klaviyo’s sandbox environment for testing:
klaviyo:
api_key: '%env(KLAVIYO_SANDBOX_API_KEY)%'
private_app_id: '%env(KLAVIYO_SANDBOX_PRIVATE_APP_ID)%'
Custom Events Extend the bundle to support custom Klaviyo events by creating a decorator:
use Driveop\KlaviyoBundle\Service\KlaviyoClientInterface;
class CustomKlaviyoClient implements KlaviyoClientInterface
{
public function __construct(private KlaviyoClient $decorated) {}
public function customEvent($email, array $data)
{
$this->decorated->trackProfile($email, [
'events' => ['Custom Event' => true],
'properties' => $data,
]);
}
}
Async Processing Offload Klaviyo calls to a message queue (e.g., Symfony Messenger) for performance:
use Symfony\Component\Messenger\MessageBusInterface;
class KlaviyoMessage
{
public function __construct(
public string $email,
public array $data,
) {}
}
// In a controller:
$bus->dispatch(new KlaviyoMessage($email, $data));
Webhook Handling Integrate Klaviyo webhooks (e.g., for campaign events) by creating a controller:
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class KlaviyoWebhookController
{
public function handle(Request $request): Response
{
$payload = json_decode($request->getContent(), true);
// Process webhook (e.g., update local DB)
return new Response('OK');
}
}
Configuration Overrides
Override bundle config per environment (e.g., klaviyo.yaml in config/packages/dev/klaviyo.yaml):
klaviyo:
debug: true
api_key: '%env(KLAVIYO_DEV_API_KEY)%'
How can I help you explore Laravel packages today?