A

Facebook ads api

public
andrei.k Jan 10, 2025 Never 23
Clone
PHP FacebookClient.php 137 lines (114 loc) | 4.53 KB
1
<?php
2
3
namespace App\Component\Facebook;
4
5
use DateTime;
6
use App\Entity\FacebookAccount;
7
use FacebookAds\Object\Fields\LocationFields;
8
use FacebookAds\Object\Values\AdsInsightsLevelValues;
9
use Symfony\Component\HttpFoundation\Response;
10
use Symfony\Contracts\HttpClient\HttpClientInterface;
11
12
class FacebookClient
13
{
14
15
private const API_URL = 'https://graph.facebook.com';
16
private const API_VERSION = 'v21.0';
17
18
private HttpClientInterface $httpClient;
19
20
private int $limit = 500;
21
22
public function __construct(HttpClientInterface $httpClient)
23
{
24
$this->httpClient = $httpClient;
25
}
26
27
public function setLimit(int $limit): self
28
{
29
$this->limit = $limit;
30
31
return $this;
32
}
33
34
public function getLimit(): int
35
{
36
return $this->limit;
37
}
38
39
/**
40
* @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
41
* @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface
42
* @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
43
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
44
* @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
45
*/
46
public function insights(
47
FacebookAccount $account,
48
DateTime $day,
49
array $fields,
50
string $level = AdsInsightsLevelValues::CAMPAIGN
51
): array {
52
$response = $this->httpClient->request(
53
'GET',
54
self::API_URL . '/' . self::API_VERSION . "/act_{$account->getFacebookAccount()}/insights", [
55
'query' => [
56
'time_range' => [
57
'since' => $day->format('Y-m-d'),
58
'until' => $day->format('Y-m-d'),
59
],
60
'fields' => implode(',', $fields),
61
'level' => $level,
62
'limit' => $this->limit,
63
'access_token' => $account->getAccessToken(),
64
]
65
]);
66
67
if ($response->getStatusCode() !== Response::HTTP_OK) {
68
throw new \RuntimeException("Code: {$response->getStatusCode()}. Message: {$response->getContent()}");
69
}
70
71
return $response->toArray()['data'];
72
}
73
74
/**
75
* @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
76
* @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface
77
* @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
78
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
79
* @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
80
*/
81
public function insightCampaigns(
82
FacebookAccount $account,
83
string $campaignId,
84
DateTime $day,
85
array $fields,
86
array $breakdowns = [LocationFields::COUNTRY],
87
string $level = AdsInsightsLevelValues::ADSET
88
): array {
89
$request = function ($after = '') use ($account, $campaignId, $day, $fields, $breakdowns, $level) {
90
$query = [
91
'time_range' => [
92
'since' => $day->format('Y-m-d'),
93
'until' => $day->format('Y-m-d'),
94
],
95
'fields' => implode(',', $fields),
96
'breakdowns' => implode(',', $breakdowns),
97
'level' => $level,
98
'limit' => $this->limit,
99
'access_token' => $account->getAccessToken(),
100
];
101
102
if (!empty($after)) {
103
$query = array_merge($query, [
104
'after' => $after,
105
]);
106
}
107
108
return $this->httpClient->request(
109
'GET',
110
self::API_URL . '/' . self::API_VERSION . "/{$campaignId}/insights", [
111
'query' => $query
112
]);
113
};
114
115
$items = [];
116
117
$after = '';
118
119
while ($after !== null) {
120
$response = $request($after);
121
122
if ($response->getStatusCode() !== Response::HTTP_OK) {
123
throw new \RuntimeException("Code: {$response->getStatusCode()}. Message: {$response->getContent()}");
124
}
125
126
if (isset($data['paging']['next'])) {
127
$after = $data['paging']['cursors']['after'];
128
} else {
129
$after = null;
130
}
131
132
$items = [...$items, ...$response->toArray()['data']];
133
}
134
135
return $items;
136
}
137
}