File: /var/www/quadcode-site/app/Helpers/ActiveCampaignHelper.php
<?php
namespace App\Helpers;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Psr\Log\LoggerInterface;
class ActiveCampaignHelper
{
private LoggerInterface $logger;
private string $host;
private string $token;
const STATUS_ACTIVE = 1;
const STATUS_UNSUBSCRIBED = 2;
const CUSTOM_FIELD_LANDING_URL = '6';
const CUSTOM_FIELD_UTM_SOURCE = '7';
const CUSTOM_FIELD_UTM_MEDIUM = '8';
const CUSTOM_FIELD_UTM_CAMPAIGN = '9';
const CUSTOM_FIELD_UTM_CONTENT = '10';
const CUSTOM_FIELD_UTM_TERMS = '11';
private static array $customFields = [
'landing_url' => self::CUSTOM_FIELD_LANDING_URL,
'utm_source' => self::CUSTOM_FIELD_UTM_SOURCE,
'utm_medium' => self::CUSTOM_FIELD_UTM_MEDIUM,
'utm_campaign' => self::CUSTOM_FIELD_UTM_CAMPAIGN,
'utm_content' => self::CUSTOM_FIELD_UTM_CONTENT,
'utm_term' => self::CUSTOM_FIELD_UTM_TERMS,
];
public function __construct()
{
$this->logger = Log::channel('activeCampaign');
$this->host = getenv('ACTIVE_CAMPAIGN_HOST');
$this->token = getenv('ACTIVE_CAMPAIGN_TOKEN');
}
public function check(): bool
{
return !empty($this->host) && !empty($this->token);
}
private function convertLead(array $data = []): array
{
$contact = ['email' => $data['email']];
if (!empty($data['first_name'])) {
$contact['firstName'] = $data['first_name'];
}
if (!empty($data['last_name'])) {
$contact['lastName'] = $data['last_name'];
}
if (!empty($data['phone'])) {
$contact['phone'] = $data['phone'];
}
$contact['fieldValues'] = [];
foreach (self::$customFields as $field => $externalKey) {
if (!empty($data[$field])) {
$contact['fieldValues'][] = [
'field' => $externalKey,
'value' => $data[$field],
];
}
}
return ['contact' => $contact];
}
private function request(string $method, string $apiMethod, array $data = [], string $title = ''): Response
{
$headers = ['Api-Token' => $this->token];
$requestLog = [
'method' => $method,
'headers' => $headers,
'host' => $this->host,
'apiMethod' => $apiMethod,
];
if (!empty($data)) {
$requestLog['data'] = $data;
}
$this->logger->info($title . ' request', $requestLog);
$time = microtime(true);
$http = Http::withHeaders($headers);
$response = match ($method) {
'POST' => $http->post($this->host . $apiMethod, $data),
default => $http->get($this->host . $apiMethod, $data),
};
$time = (microtime(true) - $time) * 1000000;
if ($time < 250000) {
// API has a rate limit of 5 requests per second per account.
usleep(250000 - $time);
}
$responseLog = [
'status' => $response->status(),
'headers' => $response->headers(),
'body' => $response->body(),
];
if ($response->successful()) {
$this->logger->info($title . ' response', $responseLog);
} else {
$this->logger->error($title . ' response', $responseLog);
}
return $response;
}
public function me(): Response
{
return $this->request('GET', '/api/3/users/me', title: 'Search contact');
}
public function searchContact(array $filter): Response
{
return $this->request('GET', '/api/3/contacts', $filter, 'Search contact');
}
public function createContact(array $data): Response
{
$data = $this->convertLead($data);
return $this->request('POST', '/api/3/contacts', $data, 'Create contact');
}
public function updateListStatus(int $contactId, int $listId, int $status = self::STATUS_ACTIVE): Response
{
$data = [
'contactList' => [
'list' => $listId,
'contact' => $contactId,
'status' => $status,
],
];
return $this->request('POST', '/api/3/contactLists', $data, 'Update list status');
}
public function subscribeContact(int $contactId, int $listId): Response
{
return $this->updateListStatus($contactId, $listId);
}
public function unsubscribeContact(int $contactId, int $listId): Response
{
return $this->updateListStatus($contactId, $listId, self::STATUS_UNSUBSCRIBED);
}
}