├── .gitignore ├── tests ├── bootstrap.php ├── KlaviyoMetricTest.php ├── KlaviyoCampaignTest.php ├── KlaviyoProfileTest.php ├── KlaviyoEventTest.php ├── KlaviyoListTest.php └── KlaviyoTemplateTest.php ├── src └── Siro │ └── Klaviyo │ ├── Exceptions │ ├── HttpException.php │ └── ApiNotFoundException.php │ ├── ApiBase.php │ ├── KlaviyoResponse.php │ ├── KlaviyoAPI.php │ ├── KlaviyoProfile.php │ ├── KlaviyoMetric.php │ ├── KlaviyoTemplate.php │ ├── KlaviyoEvent.php │ ├── KlaviyoCampaign.php │ └── KlaviyoList.php ├── phpunit.xml ├── .travis.yml ├── LICENSE ├── composer.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /.idea/ 3 | composer.lock 4 | .phpunit.result.cache 5 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/KlaviyoCampaignTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | ./tests/ 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Siro/Klaviyo/ApiBase.php: -------------------------------------------------------------------------------- 1 | apiKey = $apiKey; 28 | $this->client = $client; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Siro/Klaviyo/KlaviyoResponse.php: -------------------------------------------------------------------------------- 1 | getStatusCode(); 18 | if ($statusCode === 200) { 19 | return json_decode((string) $response->getBody()); 20 | } 21 | 22 | return null; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.1 5 | - 7.2 6 | - 7.3 7 | - 7.4 8 | - nightly 9 | 10 | env: 11 | jobs: 12 | - DEPS=lowest 13 | - DEPS=latest 14 | global: 15 | - COMPOSER_ARGS="--no-interaction" 16 | 17 | jobs: 18 | allow_failures: 19 | - php: nightly 20 | env: 21 | global: 22 | - COMPOSER_ARGS="--no-interaction --prefer-lowest" 23 | 24 | before_script: 25 | - if [[ $DEPS == 'latest' ]]; then travis_retry composer update --prefer-stable $COMPOSER_ARGS ; fi 26 | - if [[ $DEPS == 'lowest' ]]; then travis_retry composer update --prefer-stable $COMPOSER_ARGS --prefer-lowest ; fi 27 | 28 | script: 29 | - composer test 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Siro Díaz Palazón 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "siro/php-klaviyo-api", 3 | "description": "Low level but elegant Klaviyo full API wrapper for PHP with asynchronous track event support", 4 | "type": "library", 5 | "license": "MIT", 6 | "keywords": [ 7 | "laravel", 8 | "klaviyo", 9 | "api", 10 | "event tracker", 11 | "event", 12 | "event tracking", 13 | "ecommerce", 14 | "event", 15 | "analytics" 16 | ], 17 | "authors": [ 18 | { 19 | "name": "Siro Diaz", 20 | "email": "sirodiaz93@gmail.com" 21 | } 22 | ], 23 | "autoload": { 24 | "psr-4": { 25 | "Siro\\Klaviyo\\": "src/Siro/Klaviyo" 26 | } 27 | }, 28 | "require": { 29 | "php": "^7.1 || ^8.0", 30 | "ext-json": "*", 31 | "guzzlehttp/guzzle": "^6.3 || ^7.0" 32 | }, 33 | "require-dev": { 34 | "squizlabs/php_codesniffer": "^3.0", 35 | "phpunit/phpunit": "^7.5.20 || ^8.5.8" 36 | }, 37 | "scripts": { 38 | "test": "phpunit", 39 | "phpcs": "phpcs --standard=PSR2 src -n", 40 | "phpcbf": "phpcbf -v -p --standard=PSR2 src" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /tests/KlaviyoProfileTest.php: -------------------------------------------------------------------------------- 1 | klaviyo = new KlaviyoAPI('pk_7f0ccf9f003cfa6838556efbf44e318f4b'); 14 | } 15 | 16 | public function testGet() 17 | { 18 | $person = $this->klaviyo->profile->get('N9mVQC'); 19 | $this->assertEquals('example@mydomain.com', $person->email); 20 | } 21 | 22 | public function testEdit() 23 | { 24 | $person = $this->klaviyo->profile->edit('N9mVQC', [ 25 | '$first_name' => 'Michael', 26 | 'role' => 'client' 27 | ]); 28 | 29 | $this->assertEquals('Michael', ((array) $person)['$first_name']); 30 | $this->assertEquals('client', $person->role); 31 | } 32 | 33 | public function testGetMetrics() 34 | { 35 | $person = $this->klaviyo->profile->getMetrics('N9mVQC'); 36 | $this->assertObjectHasAttribute('count', $person); 37 | $this->assertObjectHasAttribute('data', $person); 38 | $this->assertIsArray($person->data); 39 | } 40 | 41 | public function testGetMetric() 42 | { 43 | $registerMetric = 'NTKpdq'; 44 | $person = $this->klaviyo->profile->getMetric('N9mVQC', $registerMetric); 45 | $this->assertObjectHasAttribute('count', $person); 46 | $this->assertObjectHasAttribute('data', $person); 47 | $this->assertIsArray($person->data); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/KlaviyoEventTest.php: -------------------------------------------------------------------------------- 1 | klaviyo = new KlaviyoAPI('pk_7f0ccf9f003cfa6838556efbf44e318f4b'); 14 | } 15 | 16 | public function testEventTrack() 17 | { 18 | $tracked = $this->klaviyo->event->track('register', [ 19 | '$email' => 'example@mydomain.com', 20 | ], [ 21 | 'register_status' => 'success', 22 | 'role' => 'client' 23 | ]); 24 | $this->assertEquals($tracked, 1); 25 | } 26 | 27 | public function testEventTrackAsync() 28 | { 29 | $promise = $this->klaviyo->event->trackAsync('register', [ 30 | '$email' => 'example@mydomain.com', 31 | ], [ 32 | 'register_status' => 'success', 33 | 'role' => 'client' 34 | ]); 35 | $res = $promise->wait(); 36 | $this->assertEquals($res->getStatusCode(), 200); 37 | $this->assertEquals(json_decode((string) $res->getBody()), 1); 38 | } 39 | 40 | /* 41 | public function testEventIdentify() 42 | { 43 | $result = $this->klaviyo->event->identify([ 44 | '$email' => 'sirocompani2@hotmail.com' 45 | ]); 46 | $this->assertEquals($result, 1); 47 | } 48 | 49 | public function testEventIdentifyAsync() 50 | { 51 | $promise = $this->klaviyo->event->identifyAsync([ 52 | '$email' => 'example@mydomain.com', 53 | '$first_name' => 'Siro', 54 | '$last_name' => 'Díaz' 55 | ]); 56 | $promise->then(function ($res) { 57 | $this->assertEquals($res->getStatusCode(), 200); 58 | $this->assertEquals(json_decode((string) $res->getBody()), 1); 59 | }); 60 | } 61 | */ 62 | } 63 | -------------------------------------------------------------------------------- /src/Siro/Klaviyo/KlaviyoAPI.php: -------------------------------------------------------------------------------- 1 | KlaviyoAPI::baseUrl, 51 | 'timeout' => 0, 52 | ]; 53 | 54 | $clientOptions = is_array($clientOptions) 55 | ? array_merge($defaultClientOptions, $clientOptions) : $defaultClientOptions; 56 | 57 | $this->apiKey = $apiKey; 58 | $this->client = new Client($clientOptions); 59 | } 60 | 61 | /** 62 | * @param string $api 63 | * @return mixed 64 | * @throws ApiNotFoundException 65 | */ 66 | public function __get($api) 67 | { 68 | if (property_exists($this, $api)) { 69 | return $this->$api; 70 | } 71 | 72 | if (!in_array($api, $this->apisAvailables)) { 73 | $message = 'Avaiable APIs: '. implode(', ', $this->apisAvailables); 74 | throw new ApiNotFoundException($message); 75 | } 76 | 77 | $apiClass = KlaviyoAPI::apiBaseName . ucfirst($api); 78 | $this->$api = new $apiClass($this->apiKey, $this->client); 79 | return $this->$api; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php-klaviyo-api 2 | 3 | [![Build Status](https://travis-ci.org/SiroDiaz/php-klaviyo-api.svg?branch=dev)](https://travis-ci.org/SiroDiaz/php-klaviyo-api) 4 | [![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3XKLA6VTYVSKW&source=url) 5 | 6 | Klaviyo API wrapper for PHP. It allows to consume the Klaviyo v1 API using a clear and simple 7 | PHP class format for make the usage user-friendly. Stuff like delete a list is as logic as doing: 8 | `$klaviyo->list->delete('asdD2e2')`. Easy, isn't it? 9 | 10 | ## Installation 11 | Installing php-klaviyo-api is simple. You just need Composer installed and added to the path. For install the 12 | current last version run: 13 | 14 | `composer require siro/php-klaviyo-api:"^1.6.0"` 15 | 16 | ## Usage 17 | 18 | ### API organization and usage 19 | 20 | The php-klaviyo-api is organized as the official Klaviyo API, really. 21 | If you want to access to event API you must do as follow: 22 | 23 | ```php 24 | // klaviyo Event API 25 | $klaviyo->event->track($event, $customerProperties, $properties); 26 | $klaviyo->event->trackAsync($event, $customerProperties, $properties); 27 | 28 | // email template API 29 | $klaviyo->template->getAll(); 30 | $klaviyo->template->create('newuser', $htmlString); 31 | 32 | // lists API 33 | $klaviyo->list->getLists(); 34 | $klaviyo->list->create('premium'); 35 | ``` 36 | 37 | A real example would be as i show here: 38 | 39 | ```php 40 | event->trackAsync( 46 | 'register', 47 | ['email' => 'federico@gmail.com'], 48 | [] 49 | ); 50 | ``` 51 | 52 | As you can see it is really easy. The code is good organized, with the same 53 | documentation that the official one. You just need to read a bit and you will see that it is simple and intuitive. 54 | 55 | ### Klaviyo Event API 56 | 57 | This API is used to track events to Klaviyo. This is the main feature 58 | and you maybe would use it. By that reason i implemented this API wrapper 59 | in this way. 60 | For load it 61 | 62 | ## Contributing 63 | This project uses **PSR-4** coding standard. If you want to make a contribution it must be important run `make sniff` for checking 64 | your code before commit the changes. 65 | At this moment it is prioritary making tests for the API so Pull requests for tests and fixes are welcome. 66 | 67 | ## Credits 68 | All credits, at this moment, are for Siro Díaz Palazón . 69 | 70 | ## Contributors 71 | At this moment main contributors are: 72 | - Siro Díaz Palazón [SiroDiaz](https://github.com/SiroDiaz) 73 | - Lukasz [Blysq](https://github.com/Blysq) 74 | 75 | ## License 76 | This project is licensed under MIT. 77 | -------------------------------------------------------------------------------- /src/Siro/Klaviyo/KlaviyoProfile.php: -------------------------------------------------------------------------------- 1 | client->get( 18 | "/api/v1/person/{$personId}", 19 | [ 20 | 'query' => [ 21 | 'api_key' => $this->apiKey 22 | ] 23 | ] 24 | ); 25 | 26 | return $this->sendResponseAsObject($response); 27 | } 28 | 29 | /** 30 | * PUT /api/v1/person/{{ PERSON_ID }} 31 | */ 32 | public function edit($personId, array $properties) 33 | { 34 | $requestParams = [ 35 | 'form_params' => [ 36 | 'api_key' => $this->apiKey 37 | ] 38 | ]; 39 | foreach ($properties as $property => $value) { 40 | $requestParams['form_params'][$property] = $value; 41 | } 42 | 43 | $response = $this->client->put("/api/v1/person/{$personId}", $requestParams); 44 | 45 | return $this->sendResponseAsObject($response); 46 | } 47 | 48 | /** 49 | * GET /api/v1/person/{{PERSON_ID}}/metrics/timeline 50 | */ 51 | public function getMetrics($personId, $since = null, $count = 100, $sort = 'desc') 52 | { 53 | $requestParams = [ 54 | 'query' => [ 55 | 'api_key' => $this->apiKey, 56 | 'count' => $count, 57 | 'sort' => $sort 58 | ] 59 | ]; 60 | if ($since !== null) { 61 | $requestParams['form_params']['since'] = $since; 62 | } 63 | 64 | $response = $this->client->get("/api/v1/person/{$personId}/metrics/timeline", $requestParams); 65 | 66 | return $this->sendResponseAsObject($response); 67 | } 68 | 69 | /** 70 | * GET /api/v1/person/{{PERSON_ID}}/metric/{{METRIC_ID}}/timeline 71 | */ 72 | public function getMetric($personId, $metricId, $since = null, $count = 100, $sort = 'desc') 73 | { 74 | $requestParams = [ 75 | 'query' => [ 76 | 'api_key' => $this->apiKey, 77 | 'count' => $count, 78 | 'sort' => $sort 79 | ] 80 | ]; 81 | if ($since !== null) { 82 | $requestParams['form_params']['since'] = $since; 83 | } 84 | 85 | $response = $this->client->get("/api/v1/person/{$personId}/metric/{$metricId}/timeline", $requestParams); 86 | 87 | return $this->sendResponseAsObject($response); 88 | } 89 | 90 | /** 91 | * GET /api/v2/person/{{ PERSON_ID }} 92 | * 93 | * @param string $value 94 | * @param string $identifier - can be 'email', 'phone_number' or 'external_id' 95 | */ 96 | public function search( $value, $identifier = 'email' ) 97 | { 98 | $response = $this->client->get( "/api/v2/people/search", 99 | [ 100 | 'query' => [ 101 | 'api_key' => $this->apiKey, 102 | $identifier => $value 103 | ] 104 | ] 105 | ); 106 | 107 | return $this->sendResponseAsObject( $response ); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Siro/Klaviyo/KlaviyoMetric.php: -------------------------------------------------------------------------------- 1 | client->get( 32 | '/api/v1/metrics', 33 | [ 34 | 'query' => [ 35 | 'api_key' => $this->apiKey, 36 | 'page' => $page, 37 | 'count' => $count 38 | ] 39 | ] 40 | ); 41 | return $this->sendResponseAsObject($response); 42 | } 43 | 44 | /** 45 | * GET /api/v1/metrics/timeline 46 | */ 47 | public function getAllTimeline($page = 0, $since = null, $count = 100, $sort = 'desc') 48 | { 49 | $data = [ 50 | 'query' => [ 51 | 'api_key' => $this->apiKey, 52 | 'page' => $page, 53 | 'count' => $count 54 | ] 55 | ]; 56 | if (!is_null($since)) { 57 | $data['query']['since'] = $since; 58 | } 59 | 60 | $response = $this->client->get('/api/v1/metrics/timeline', $data); 61 | return $this->sendResponseAsObject($response); 62 | } 63 | 64 | /** 65 | * GET /api/v1/metric/{{METRIC_ID}}/timeline 66 | */ 67 | public function getMetricTimeline($metricId, $since = null, $count = 100, $sort = 'desc') 68 | { 69 | $data = [ 70 | 'query' => [ 71 | 'api_key' => $this->apiKey, 72 | 'count' => $count, 73 | 'sort' => $sort 74 | ] 75 | ]; 76 | if (!is_null($since)) { 77 | $data['query']['since'] = $since; 78 | } 79 | 80 | $response = $this->client->get("/api/v1/metric/{$metricId}/timeline", $data); 81 | return $this->sendResponseAsObject($response); 82 | } 83 | 84 | /** 85 | * GET /api/v1/metric/{{METRIC_ID}}/export 86 | */ 87 | public function export($metricId, $start = null, $end = null, $unit = 'day', $measurement = null, $where = null, $by = '', $count = 25) 88 | { 89 | $data = [ 90 | 'query' => [ 91 | 'api_key' => $this->apiKey, 92 | 'count' => $count, 93 | 'unit' => $unit 94 | ] 95 | ]; 96 | if (!is_null($start) && $this->isValidDate($start)) { 97 | $data['query']['start_date'] = $start; 98 | } 99 | if (!is_null($end) && $this->isValidDate($end)) { 100 | $data['query']['end_date'] = $end; 101 | } 102 | if (is_null($where) && !is_empty($by)) { 103 | $data['query']['by'] = urlencode($by); 104 | } elseif (!is_null($where) && is_array($where) && is_empty($by)) { 105 | $data['query']['where'] = json_encode(array_values($where)); 106 | } 107 | 108 | $response = $this->client->get("/api/v1/metric/{$metricId}/export", $data); 109 | return $this->sendResponseAsObject($response); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Siro/Klaviyo/KlaviyoTemplate.php: -------------------------------------------------------------------------------- 1 | client->get( 15 | '/api/v1/email-templates', 16 | [ 17 | 'query' => [ 18 | 'api_key' => $this->apiKey 19 | ] 20 | ] 21 | ); 22 | 23 | return $this->sendResponseAsObject($response); 24 | } 25 | 26 | /** 27 | * POST /api/v1/email-templates 28 | */ 29 | public function create($name, $htmlTemplate) 30 | { 31 | $requestParams = [ 32 | 'form_params' => [ 33 | 'api_key' => $this->apiKey, 34 | 'name' => $name, 35 | 'html' => $htmlTemplate, 36 | ] 37 | ]; 38 | $response = $this->client->post('/api/v1/email-templates', $requestParams); 39 | 40 | return $this->sendResponseAsObject($response); 41 | } 42 | 43 | /** 44 | * PUT /api/v1/email-template/{{ TEMPLATE_ID }} 45 | */ 46 | public function update($templateId, $name, $htmlTemplate) 47 | { 48 | $requestParams = [ 49 | 'form_params' => [ 50 | 'api_key' => $this->apiKey, 51 | 'name' => $name, 52 | 'html' => $htmlTemplate, 53 | ] 54 | ]; 55 | $response = $this->client->put("/api/v1/email-template/{$templateId}", $requestParams); 56 | 57 | return $this->sendResponseAsObject($response); 58 | } 59 | 60 | /** 61 | * DELETE /api/v1/email-template/{{ TEMPLATE_ID }} 62 | */ 63 | public function delete($templateId) 64 | { 65 | $requestParams = [ 66 | 'form_params' => [ 67 | 'api_key' => $this->apiKey, 68 | ] 69 | ]; 70 | $response = $this->client->delete("/api/v1/email-template/{$templateId}", $requestParams); 71 | return $this->sendResponseAsObject($response); 72 | } 73 | 74 | /** 75 | * POST /api/v1/email-template/{{ TEMPLATE_ID }}/clone 76 | */ 77 | public function clone($templateId, $newName) 78 | { 79 | $requestParams = [ 80 | 'form_params' => [ 81 | 'api_key' => $this->apiKey, 82 | 'name' => $newName 83 | ] 84 | ]; 85 | $response = $this->client->post("/api/v1/email-template/{$templateId}/clone", $requestParams); 86 | return $this->sendResponseAsObject($response); 87 | } 88 | 89 | /** 90 | * POST /api/v1/email-template/{{ TEMPLATE_ID }}/render 91 | */ 92 | public function render($templateId, array $context = []) 93 | { 94 | $requestParams = [ 95 | 'form_params' => [ 96 | 'api_key' => $this->apiKey, 97 | 'context' => json_encode($context) 98 | ] 99 | ]; 100 | $response = $this->client->post("/api/v1/email-template/{$templateId}/render", $requestParams); 101 | return $this->sendResponseAsObject($response); 102 | } 103 | 104 | /** 105 | * POST /api/v1/email-template/{{ TEMPLATE_ID }}/send 106 | */ 107 | public function renderAndSend($templateId, $fromEmail, $fromName, $subject, $to, array $context = []) 108 | { 109 | $requestParams = [ 110 | 'form_params' => [ 111 | 'api_key' => $this->apiKey, 112 | 'from_email' => $fromEmail, 113 | 'from_name' => $fromName, 114 | 'subject' => $subject, 115 | 'context' => json_encode($context) 116 | ] 117 | ]; 118 | 119 | if (is_array($to)) { 120 | $to = json_encode($to); 121 | } 122 | $requestParams['form_params']['to'] = $to; 123 | 124 | $response = $this->client->post("/api/v1/email-template/{$templateId}/send", $requestParams); 125 | return $this->sendResponseAsObject($response); 126 | } 127 | 128 | /** 129 | * POST /api/v1/email-template/{{ TEMPLATE_ID }}/send 130 | */ 131 | public function send($templateId, $fromEmail, $fromName, $subject, $to, array $context = []) 132 | { 133 | return $this->renderAndSend($templateId, $fromEmail, $fromName, $subject, $to, $context); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /tests/KlaviyoListTest.php: -------------------------------------------------------------------------------- 1 | klaviyo = new KlaviyoAPI('pk_7f0ccf9f003cfa6838556efbf44e318f4b'); 14 | 15 | $allLists = $this->klaviyo->list->getLists(); 16 | 17 | foreach ($allLists as $list) { 18 | $this->klaviyo->list->delete($list->list_id); 19 | } 20 | } 21 | 22 | public function testCreate() 23 | { 24 | $list = $this->klaviyo->list->create('Test list'); 25 | 26 | $this->assertObjectHasAttribute('list_id', $list); 27 | } 28 | 29 | public function testList() 30 | { 31 | $this->klaviyo->list->create('Test list'); 32 | $this->klaviyo->list->create('Another list'); 33 | $allLists = $this->klaviyo->list->getLists(); 34 | 35 | $this->assertEquals(2, count($allLists)); 36 | } 37 | 38 | public function testGet() 39 | { 40 | $list = $this->klaviyo->list->create('List for get'); 41 | $listInfo = $this->klaviyo->list->get($list->list_id); 42 | 43 | $this->assertEquals('List for get', $listInfo->list_name); 44 | } 45 | 46 | public function testUpdate() 47 | { 48 | $list = $this->klaviyo->list->create('List for get'); 49 | $this->klaviyo->list->update($list->list_id, 'New list name'); 50 | $listInfo = $this->klaviyo->list->get($list->list_id); 51 | 52 | $this->assertEquals('New list name', $listInfo->list_name); 53 | } 54 | 55 | public function testDelete() 56 | { 57 | $list = $this->klaviyo->list->create('List for get'); 58 | $this->klaviyo->list->delete($list->list_id); 59 | 60 | $allLists = $this->klaviyo->list->getLists(); 61 | $this->assertEquals(0, count($allLists)); 62 | } 63 | 64 | public function testAddMember() 65 | { 66 | $list = $this->klaviyo->list->create('List for get'); 67 | $member = $this->klaviyo->list->addMember( 68 | $list->list_id, 69 | [ 70 | [ 71 | 'email' => 'example@mydomain.com', 72 | ] 73 | ] 74 | ); 75 | 76 | $this->assertEquals('example@mydomain.com', $member[0]->email); 77 | $this->assertCount(1, $member); 78 | } 79 | 80 | public function testAddMembers() 81 | { 82 | $list = $this->klaviyo->list->create('List for get'); 83 | $members = $this->klaviyo->list->addMember($list->list_id, [ 84 | [ 85 | 'email' => 'example@mydomain.com', 'properties' => ['role' => 'client'], 86 | ], 87 | [ 88 | 'email' => 'jhondoe@mydomain.com' 89 | ] 90 | ], false); 91 | 92 | $this->assertEquals(2, count($members)); 93 | } 94 | 95 | public function testMemberExistsInList() 96 | { 97 | $list = $this->klaviyo->list->create('List for get'); 98 | $this->klaviyo->list->addMember($list->list_id, [ 99 | [ 100 | 'email' => 'example@mydomain.com', 'properties' => ['role' => 'client'], 101 | ], 102 | [ 103 | 'email' => 'jhondoe@mydomain.com' 104 | ] 105 | ], false); 106 | $this->assertTrue($this->klaviyo->list->memberExistsInList($list->list_id, ['example@mydomain.com', 'jhondoe@mydomain.com'])); 107 | } 108 | 109 | public function testMembersDontExistInList() 110 | { 111 | $list = $this->klaviyo->list->create('List for get'); 112 | $this->klaviyo->list->addMember($list->list_id, [ 113 | [ 114 | 'email' => 'example@mydomain.com', 'properties' => ['role' => 'client'], 115 | ], 116 | [ 117 | 'email' => 'jhondoe@mydomain.com' 118 | ] 119 | ]); 120 | $this->assertFalse($this->klaviyo->list->memberExistsInList($list->list_id, ['jaime@mydomain.com', 'jhondoe@mydomain.com'])); 121 | } 122 | 123 | public function testDeleteMemberFromList() 124 | { 125 | $list = $this->klaviyo->list->create('List for get'); 126 | $members = $this->klaviyo->list->addMember($list->list_id, [ 127 | [ 128 | 'email' => 'example@mydomain.com', 'properties' => ['role' => 'client'], 129 | ], 130 | [ 131 | 'email' => 'jhondoe@mydomain.com' 132 | ] 133 | ]); 134 | 135 | $members = $this->klaviyo->list->deleteMembers($list->list_id, ['example@mydomain.com', 'jhondoe@mydomain.com']); 136 | $this->assertFalse($this->klaviyo->list->memberExistsInList($list->list_id, ['example@mydomain.com', 'jhondoe@mydomain.com'])); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /tests/KlaviyoTemplateTest.php: -------------------------------------------------------------------------------- 1 | klaviyo = new KlaviyoAPI('pk_7f0ccf9f003cfa6838556efbf44e318f4b'); 14 | } 15 | 16 | public function testCreate() 17 | { 18 | $tmpl = " 19 | 20 | 21 |

Welcome to our website {{name}}!

22 |

Ey, we are doing great stuffs.

23 | 24 | 25 | "; 26 | $template = $this->klaviyo->template->create('Register template', $tmpl); 27 | $this->klaviyo->template->delete($template->id); 28 | 29 | $this->assertEquals('Register template', $template->name); 30 | $this->assertEquals('email-template', $template->object); 31 | } 32 | 33 | public function testClone() 34 | { 35 | $tmpl = " 36 | 37 | 38 |

Welcome to our website {{name}}!

39 |

Ey, we are doing great stuffs.

40 | 41 | 42 | "; 43 | $template = $this->klaviyo->template->create('Register template', $tmpl); 44 | $cloned = $this->klaviyo->template->clone($template->id, 'Register template clone'); 45 | 46 | $this->assertEquals('Register template', $template->name); 47 | $this->assertEquals('email-template', $template->object); 48 | $this->assertEquals('Register template clone', $cloned->name); 49 | $this->assertEquals('email-template', $cloned->object); 50 | 51 | $this->klaviyo->template->delete($template->id); 52 | $this->klaviyo->template->delete($cloned->id); 53 | } 54 | 55 | public function testGetAll() 56 | { 57 | $tmpl = " 58 | 59 | 60 |

Welcome to our website {{name}}!

61 |

Ey, we are doing great stuffs.

62 | 63 | 64 | "; 65 | $template = $this->klaviyo->template->create('Register template', $tmpl); 66 | $cloned = $this->klaviyo->template->clone($template->id, 'Register template clone'); 67 | $allTmpls = $this->klaviyo->template->getAll(); 68 | 69 | $this->klaviyo->template->delete($template->id); 70 | $this->klaviyo->template->delete($cloned->id); 71 | 72 | $this->assertObjectHasAttribute('total', $allTmpls); 73 | $this->assertIsArray($allTmpls->data); 74 | } 75 | 76 | public function testDelete() 77 | { 78 | $tmpl = " 79 | 80 | 81 |

Welcome to our website {{name}}!

82 |

Ey, we are doing great stuffs.

83 | 84 | 85 | "; 86 | $template = $this->klaviyo->template->create('Register template', $tmpl); 87 | $cloned = $this->klaviyo->template->clone($template->id, 'Register template clone'); 88 | $allTmpls = $this->klaviyo->template->getAll(); 89 | 90 | $this->assertObjectHasAttribute('total', $allTmpls); 91 | $this->assertIsArray( $allTmpls->data); 92 | 93 | $this->klaviyo->template->delete($template->id); 94 | $this->klaviyo->template->delete($cloned->id); 95 | $allTmpls = $this->klaviyo->template->getAll(); 96 | 97 | $this->assertObjectHasAttribute('total', $allTmpls); 98 | $this->assertIsArray( $allTmpls->data); 99 | } 100 | 101 | public function testUpdateName() 102 | { 103 | $tmpl = " 104 | 105 | 106 |

Welcome to our website {{name}}!

107 |

Ey, we are doing great stuffs.

108 | 109 | 110 | "; 111 | $template = $this->klaviyo->template->create('Register template', $tmpl); 112 | $updated = $this->klaviyo->template->update($template->id, 'Register template updated', $tmpl); 113 | 114 | $this->klaviyo->template->delete($updated->id); 115 | $allTmpls = $this->klaviyo->template->getAll(); 116 | 117 | $this->assertObjectHasAttribute('total', $allTmpls); 118 | $this->assertIsArray($allTmpls->data); 119 | } 120 | 121 | /* 122 | public function testRender() 123 | { 124 | $tmpl = " 125 | 126 | 127 |

Welcome to our website {{name}}!

128 |

Ey, we are doing great stuffs.

129 | 130 | 131 | "; 132 | $template = $this->klaviyo->template->create('Register template', $tmpl); 133 | 134 | $this->klaviyo->template->delete($template->id); 135 | 136 | // $this->assertEquals(7, $allTmpls->total); 137 | // $this->assertIsArray($allTmpls->data); 138 | } 139 | */ 140 | } 141 | -------------------------------------------------------------------------------- /src/Siro/Klaviyo/KlaviyoEvent.php: -------------------------------------------------------------------------------- 1 | $this->apiKey, 31 | 'event' => $event, 32 | 'customer_properties' => $customerProperties, 33 | 'properties' => $properties, 34 | 'time' => $timestamp 35 | ]; 36 | 37 | $response = $this->client->get( 38 | '/api/track', 39 | [ 40 | 'query' => [ 41 | 'data' => base64_encode(json_encode($data)) 42 | ] 43 | ] 44 | ); 45 | 46 | return $this->sendResponseAsObject($response); 47 | } 48 | 49 | /** 50 | * Asynchronous track event version. 51 | * GET /api/track 52 | * 53 | * @param string $event The event name. For example, 'register'. 54 | * @param array $customerProperties An array containing the email (client email). 55 | * @param array $properties An array containing all extra data of the client, as 56 | * name, surname, language, city, etc. 57 | * @param mixed $timestamp the time in UNIX timestamp format. null by default. 58 | * @return \GuzzleHttp\Promise\PromiseInterface a promise than must be treated. 59 | */ 60 | public function trackAsync($event, array $customerProperties, array $properties, $timestamp = null) 61 | { 62 | $data = [ 63 | 'token' => $this->apiKey, 64 | 'event' => $event, 65 | 'customer_properties' => $customerProperties, 66 | 'properties' => $properties, 67 | 'time' => $timestamp 68 | ]; 69 | 70 | return $this->client->getAsync( 71 | '/api/track', 72 | [ 73 | 'query' => [ 74 | 'data' => base64_encode(json_encode($data)) 75 | ] 76 | ] 77 | ); 78 | } 79 | 80 | /** 81 | * The Identify API endpoint is /api/identify, which is used to track properties 82 | * about an individual without tracking an associated event. 83 | * It encodes the following data in a dictionary or hash. 84 | * GET /api/identify 85 | * 86 | * @param array $properties 87 | * @return object 88 | * @throws \Exception 89 | */ 90 | public function identify(array $properties) 91 | { 92 | if ((!array_key_exists('$email', $properties) || empty($properties['$email'])) 93 | && (!array_key_exists('$id', $properties) || empty($properties['$id'])) 94 | ) { 95 | throw new \Exception('You must identify a user by email or ID.'); 96 | } 97 | $data = [ 98 | 'token' => $this->apiKey, 99 | 'properties' => $properties 100 | ]; 101 | 102 | $response = $this->client->get( 103 | '/api/identify', 104 | [ 105 | 'query' => [ 106 | 'data' => base64_encode(json_encode($data)) 107 | ] 108 | ] 109 | ); 110 | 111 | return $this->sendResponseAsObject($response); 112 | } 113 | 114 | /** 115 | * The Identify API endpoint in a asynchronous version. 116 | * GET /api/identify. 117 | * 118 | * @param array $properties an array of properties listed in https://www.klaviyo.com/docs/http-api. 119 | * @return GuzzleHttp\Promise\PromiseInterface a promise than must be treated. 120 | * @throws \Exception 121 | */ 122 | public function identifyAsync(array $properties) 123 | { 124 | if ((!array_key_exists('$email', $properties) || empty($properties['$email'])) 125 | && (!array_key_exists('$id', $properties) || empty($properties['$id'])) 126 | ) { 127 | throw new \Exception('You must identify a user by email or ID.'); 128 | } 129 | $data = [ 130 | 'token' => $this->apiKey, 131 | 'properties' => $properties 132 | ]; 133 | 134 | return $this->client->getAsync( 135 | '/api/identify', 136 | [ 137 | 'query' => [ 138 | 'data' => base64_encode(json_encode($data)) 139 | ] 140 | ] 141 | ); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/Siro/Klaviyo/KlaviyoCampaign.php: -------------------------------------------------------------------------------- 1 | client->get( 17 | "/api/v1/campaigns", 18 | [ 19 | 'query' => [ 20 | 'api_key' => $this->apiKey, 21 | 'page' => $page, 22 | 'count' => $count 23 | ] 24 | ] 25 | ); 26 | 27 | return $this->sendResponseAsObject($response); 28 | } 29 | 30 | /** 31 | * POST /api/v1/campaigns 32 | */ 33 | public function create($listId, $templateId, $fromEmail, $fromName, $subject, $name = '', $useSmartSending = true, $addGoogleAnalytics = false) 34 | { 35 | $requestParams = [ 36 | 'form_params' => [ 37 | 'api_key' => $this->apiKey, 38 | 'list_id' => $listId, 39 | 'template_id' => $templateId, 40 | 'from_email' => $fromEmail, 41 | 'from_name' => $fromName, 42 | 'subject' => $subject, 43 | 'use_smart_sending' => $useSmartSending, 44 | 'add_google_analytics' => $addGoogleAnalytics, 45 | ] 46 | ]; 47 | 48 | if (!empty($name)) { 49 | $requestParams['form_params']['name'] = $name; 50 | } 51 | 52 | $response = $this->client->post("/api/v1/campaigns", $requestParams); 53 | 54 | return $this->sendResponseAsObject($response); 55 | } 56 | 57 | /** 58 | * GET /api/v1/campaign/{{ CAMPAIGN_ID }} 59 | */ 60 | public function get($campaignId) 61 | { 62 | $response = $this->client->get( 63 | "/api/v1/campaign/{$campaignId}", 64 | [ 65 | 'query' => [ 66 | 'api_key' => $this->apiKey 67 | ] 68 | ] 69 | ); 70 | 71 | return $this->sendResponseAsObject($response); 72 | } 73 | 74 | /** 75 | * PUT /api/v1/campaign/{{ CAMPAIGN_ID }} 76 | */ 77 | public function update($campaignId, $listId = null, $templateId = null, $fromEmail = null, $fromName = null, $subject = null, $name = null, $useSmartSending = null, $addGoogleAnalytics = null) 78 | { 79 | $requestParams = [ 80 | 'form_params' => [ 81 | 'api_key' => $this->apiKey, 82 | ] 83 | ]; 84 | if (!is_null($listId)) { 85 | $requestParams['form_params']['list_id'] = $listId; 86 | } 87 | if (!is_null($templateId)) { 88 | $requestParams['form_params']['template_id'] = $templateId; 89 | } 90 | if (!is_null($fromEmail)) { 91 | $requestParams['form_params']['from_email'] = $fromEmail; 92 | } 93 | if (!is_null($fromName)) { 94 | $requestParams['form_params']['from_name'] = $fromName; 95 | } 96 | if (!is_null($subject)) { 97 | $requestParams['form_params']['subject'] = $subject; 98 | } 99 | if (!is_null($useSmartSending)) { 100 | $requestParams['form_params']['use_smart_sending'] = $useSmartSending; 101 | } 102 | if (!is_null($name)) { 103 | $requestParams['form_params']['name'] = $name; 104 | } 105 | if (!is_null($addGoogleAnalytics)) { 106 | $requestParams['form_params']['add_google_analytics'] = $addGoogleAnalytics; 107 | } 108 | 109 | $response = $this->client->put("/api/v1/campaign/{$campaignId}", $requestParams); 110 | 111 | return $this->sendResponseAsObject($response); 112 | } 113 | 114 | /** 115 | * POST /api/v1/campaign/{{ CAMPAIGN_ID }}/send 116 | */ 117 | public function sendNow($campaignId) 118 | { 119 | $response = $this->client->post( 120 | "/api/v1/campaign/{$campaignId}/send", 121 | [ 122 | 'query' => [ 123 | 'api_key' => $this->apiKey 124 | ] 125 | ] 126 | ); 127 | 128 | return $this->sendResponseAsObject($response); 129 | } 130 | 131 | /** 132 | * POST /api/v1/campaign/{{ CAMPAIGN_ID }}/schedule 133 | */ 134 | public function schedule($campaignId, $sendTime) 135 | { 136 | $options = [ 137 | 'form_params' => [ 138 | 'api_key' => $this->apiKey, 139 | ] 140 | ]; 141 | if (is_int($sendTime)) { 142 | $options['form_params']['send_time'] = date("Y-m-d H:i:s", $sendTime); 143 | } else { 144 | $options['form_params']['send_time'] = $sendTime; 145 | } 146 | 147 | $response = $this->client->post("/api/v1/campaign/{$campaignId}/schedule", $options); 148 | return $this->sendResponseAsObject($response); 149 | } 150 | 151 | /** 152 | * POST /api/v1/campaign/{{ CAMPAIGN_ID }}/cancel 153 | */ 154 | public function cancel($campaignId) 155 | { 156 | $options = [ 157 | 'form_params' => [ 158 | 'api_key' => $this->apiKey 159 | ] 160 | ]; 161 | $response = $this->client->post("/api/v1/campaign/{$campaignId}/cancel", $options); 162 | return $this->sendResponseAsObject($response); 163 | } 164 | 165 | /** 166 | * POST /api/v1/campaign/{{ CAMPAIGN_ID }}/clone 167 | */ 168 | public function clone($campaignId, $newName, $listId) 169 | { 170 | $options = [ 171 | 'form_params' => [ 172 | 'api_key' => $this->apiKey, 173 | 'name' => $newName, 174 | 'list_id' => $listId 175 | ] 176 | ]; 177 | $response = $this->client->post("/api/v1/campaign/{$campaignId}/clone", $options); 178 | return $this->sendResponseAsObject($response); 179 | } 180 | 181 | /** 182 | * GET /api/v1/campaign/{{ CAMPAIGN_ID }}/recipients 183 | */ 184 | public function getRecipients($campaignId, $count = 5000, $sort = 'asc', $offset = '') 185 | { 186 | $options = [ 187 | 'query' => [ 188 | 'count' => $count, 189 | 'api_key' => $this->apiKey, 190 | 'sort' => $sort, 191 | ] 192 | ]; 193 | if (!empty($offset)) { 194 | $options['query']['offset'] = $offset; 195 | } 196 | $response = $this->client->get("/api/v1/campaign/{$campaignId}/recipients", $options); 197 | 198 | return $this->sendResponseAsObject($response); 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /src/Siro/Klaviyo/KlaviyoList.php: -------------------------------------------------------------------------------- 1 | client->get( 45 | "/api/v2/lists", 46 | [ 47 | 'form_params' => [ 48 | 'api_key' => $this->apiKey, 49 | ] 50 | ] 51 | ); 52 | 53 | return $this->sendResponseAsObject($response); 54 | } 55 | 56 | /** 57 | * Create a new list. Currently this resources only supports creating standard lists. 58 | * 59 | * @param string $name 60 | * POST /api/v2/lists 61 | */ 62 | public function create($name) 63 | { 64 | $requestParams = [ 65 | 'form_params' => [ 66 | 'api_key' => $this->apiKey, 67 | 'list_name' => $name, 68 | ] 69 | ]; 70 | $response = $this->client->post("/api/v2/lists", $requestParams); 71 | 72 | return $this->sendResponseAsObject($response); 73 | } 74 | 75 | /** 76 | * Summary information for the list specified that includes 77 | * the name, ID, type, number of members, when it was created and last updated. 78 | * 79 | * GET /api/v2/list/{{ LIST_ID }} 80 | * 81 | * @param string $listId 82 | */ 83 | public function get($listId) 84 | { 85 | $response = $this->client->get( 86 | "/api/v2/list/{$listId}", 87 | [ 88 | 'query' => [ 89 | 'api_key' => $this->apiKey 90 | ] 91 | ] 92 | ); 93 | 94 | return $this->sendResponseAsObject($response); 95 | } 96 | 97 | /** 98 | * Update details of the list. Currently this only support updating the 99 | * name of the list. 100 | * 101 | * PUT /api/v2/list/{{ LIST_ID }} 102 | * 103 | * @param string $listId The list ID. 104 | * @param string $name New name. 105 | * @return mixed Null if the request fails or an stdclass object if is successful. 106 | */ 107 | public function update($listId, $name) 108 | { 109 | $requestParams = [ 110 | 'form_params' => [ 111 | 'api_key' => $this->apiKey, 112 | 'list_name' => $name 113 | ] 114 | ]; 115 | $response = $this->client->put("/api/v2/list/{$listId}", $requestParams); 116 | 117 | return $this->sendResponseAsObject($response); 118 | } 119 | 120 | /** 121 | * PUT /api/v2/list/{{ LIST_ID }} 122 | */ 123 | public function delete($listId) 124 | { 125 | $response = $this->client->delete( 126 | "/api/v2/list/{$listId}", 127 | [ 128 | 'query' => [ 129 | 'api_key' => $this->apiKey 130 | ] 131 | ] 132 | ); 133 | 134 | return $this->sendResponseAsObject($response); 135 | } 136 | 137 | /** 138 | * GET /api/v2/list/{$listId}/members 139 | */ 140 | public function memberExistsInList($listId, $email) 141 | { 142 | $emails = $email; 143 | if (!is_array($email)) { 144 | $emails = [$email]; 145 | } 146 | $options = [ 147 | 'form_params' => [ 148 | 'api_key' => $this->apiKey, 149 | 'emails' => $emails 150 | ] 151 | ]; 152 | $response = $this->client->get("/api/v2/list/{$listId}/members", [ 153 | RequestOptions::JSON => $options['form_params'], 154 | $options 155 | ]); 156 | 157 | return count($this->sendResponseAsObject($response)) === count($emails); 158 | } 159 | 160 | /** 161 | * GET /api/v1/segment/{{ SEGMENT_ID }}/members 162 | */ 163 | public function memberExistsInSegment($segmentId, $email) 164 | { 165 | $emailFormat = $email; 166 | if (is_array($email)) { 167 | $emailFormat = implode(',', $email); 168 | } 169 | $options = [ 170 | 'query' => [ 171 | 'api_key' => $this->apiKey, 172 | 'email' => $emailFormat 173 | ] 174 | ]; 175 | $response = $this->client->get("/api/v2/segment/{$segmentId}/members", $options); 176 | 177 | if ($response->getStatusCode() === 200) { 178 | $resObj = json_decode((string) $response->getBody()); 179 | if (is_array($email)) { 180 | return $resObj->total === count($email); 181 | } 182 | 183 | return (bool) $resObj->total; 184 | } 185 | 186 | return null; 187 | } 188 | 189 | /** 190 | * Checks if the email/s are submited in a list or segment 191 | * 192 | * @param string $id The segment or list ID. 193 | * @param mixed $email The user email to check if exists. 194 | * @param string $type List or segment 195 | * @return bool True if all emails are inside the list or segment. 196 | */ 197 | public function memberExists($id, $email, $type = 'list') 198 | { 199 | if ($type === 'list') { 200 | return $this->memberExistsInList($id, $email); 201 | } elseif ($type === 'segment') { 202 | return $this->memberExistsInSegment($id, $email); 203 | } else { 204 | throw new Exception('type not allowed. Only "list" and "segment"'); 205 | } 206 | } 207 | 208 | /** 209 | * Adds a new person to the specified list. If a person with that 210 | * email address does not already exist, a new person is first added to Klaviyo. 211 | * If someone is unsubscribed from the specified list, they will not be subscribed. 212 | * To re-subscribe someone, you must manually remove them from the 213 | * unsubscribe list in Klaviyo on the members page for the specified list. 214 | * POST /api/v2/list/{{ LIST_ID }}/members 215 | * 216 | * @param string $listId The id of the id. 217 | * @param array $profiles An array of properties such as names. 218 | * @return mixed Null if the request fails or an stdclass object if is successful 219 | */ 220 | public function addMember($listId, array $profiles) 221 | { 222 | foreach ($profiles as $profile) { 223 | if (!array_key_exists('email', $profile)) { 224 | throw new Exception('"email" key not found'); 225 | } 226 | } 227 | $formParams = [ 228 | 'form_params' => [ 229 | 'api_key' => $this->apiKey, 230 | 'profiles' => $profiles 231 | ], 232 | ]; 233 | 234 | $response = $this->client->post("/api/v2/list/{$listId}/members", [ 235 | RequestOptions::JSON => $formParams['form_params'], 236 | $formParams 237 | ]); 238 | return $this->sendResponseAsObject($response); 239 | } 240 | 241 | /** 242 | * Batch Removing People from a List 243 | * Removes multiple people from the specified list. For each person, 244 | * if a person with that email address is a member of that list, 245 | * they are removed. 246 | * DELETE /api/v2/list/{{ LIST_ID }}/members/batch 247 | * 248 | * @param string $listId The list id. 249 | * @param array $emails The list of user emails to delete. 250 | * @return mixed Null if the request fails or an stdclass object if is successful. 251 | */ 252 | public function deleteMembers($listId, array $emails) 253 | { 254 | $options = [ 255 | 'form_params' => [ 256 | 'api_key' => $this->apiKey, 257 | 'emails' => $emails 258 | ] 259 | ]; 260 | $response = $this->client->delete("/api/v2/list/{$listId}/members", [ 261 | RequestOptions::JSON => $options['form_params'], 262 | $options 263 | ]); 264 | 265 | return $this->sendResponseAsObject($response); 266 | } 267 | 268 | /** 269 | * POST https://a.klaviyo.com/api/v2/list/{LIST_ID}/subscribe 270 | */ 271 | public function subscribe($listId, array $profiles) 272 | { 273 | foreach ($profiles as $profile) { 274 | if (!array_key_exists('email', $profile)) { 275 | throw new Exception('"email" key not found'); 276 | } 277 | } 278 | $options = [ 279 | 'form_params' => [ 280 | 'api_key' => $this->apiKey, 281 | 'profiles' => $profiles 282 | ] 283 | ]; 284 | $response = $this->client->post("/api/v2/list/{$listId}/subscribe", [ 285 | RequestOptions::JSON => $options['form_params'], 286 | $options 287 | ]); 288 | 289 | return $this->sendResponseAsObject($response); 290 | } 291 | 292 | /** 293 | * GET https://a.klaviyo.com/api/v2/list/{LIST_ID}/subscribe 294 | */ 295 | public function checkSubscriptions($listId, array $emails) 296 | { 297 | $options = [ 298 | 'form_params' => [ 299 | 'api_key' => $this->apiKey, 300 | 'emails' => $emails 301 | ] 302 | ]; 303 | 304 | $response = $this->client->get( 305 | "/api/v2/list/{$listId}/subscribe", 306 | [ 307 | RequestOptions::JSON => $options['form_params'], 308 | $options 309 | ] 310 | ); 311 | 312 | return $this->sendResponseAsObject($response); 313 | } 314 | 315 | /** 316 | * Unsubscribe and remove profiles from a list. 317 | * DELETE https://a.klaviyo.com/api/v2/list/{LIST_ID}/subscribe 318 | */ 319 | public function unsubscribe($listId, array $emails) 320 | { 321 | $options = [ 322 | 'form_params' => [ 323 | 'api_key' => $this->apiKey, 324 | 'emails' => $emails 325 | ] 326 | ]; 327 | 328 | $response = $this->client->delete( 329 | "/api/v2/list/{$listId}/subscribe", 330 | [ 331 | RequestOptions::JSON => $options['form_params'], 332 | $options 333 | ] 334 | ); 335 | 336 | return $this->sendResponseAsObject($response); 337 | } 338 | 339 | /** 340 | * Get all of the emails that have been excluded from a list along 341 | * with the exclusion reason and exclusion time. 342 | * This endpoint uses batching to return the records, so for a large list 343 | * multiple calls will need to be made to get all of the records. 344 | * 345 | * GET https://a.klaviyo.com/api/v2/list/{LIST_ID}/exclusions/all 346 | */ 347 | public function getAllExclusions($listId, $marker = null) 348 | { 349 | $options = [ 350 | 'form_params' => [ 351 | 'api_key' => $this->apiKey 352 | ] 353 | ]; 354 | 355 | if (!is_null($marker)) { 356 | $options['form_params']['marker'] = (int) $marker; 357 | } 358 | 359 | $response = $this->client->get( 360 | "/api/v2/list/{$listId}/exclusions/all", 361 | [ 362 | RequestOptions::JSON => $options['form_params'], 363 | $options 364 | ] 365 | ); 366 | 367 | return $this->sendResponseAsObject($response); 368 | } 369 | 370 | /** 371 | * GET /api/v2/group/{LIST_ID or SEGMENT_ID}/members/all 372 | */ 373 | public function getListMembers($listId, $marker = null) 374 | { 375 | $formParams = [ 376 | 'form_params' => [ 377 | 'api_key' => $this->apiKey 378 | ] 379 | ]; 380 | 381 | if ($marker) { 382 | $formParams['form_params']['marker'] = $marker; 383 | } 384 | 385 | $response = $this->client->get( 386 | "/api/v2/group/{$listId}/members/all", 387 | $formParams 388 | ); 389 | return $this->sendResponseAsObject($response); 390 | } 391 | } 392 | --------------------------------------------------------------------------------