Yii Framework. Yii extension for customer.io

August 15, 2016 16 Yehor Rykhnov

Are you use yii and customer.io for send emails? Then this simple example of extension for quick start and sending emails from your site through customer.io for you.

Create a class to work with sending mail through customer.io on the path: protected/extensions/customerio/CustomerIO.php

And add the following code to it:

<?php

class CustomerIO extends CComponent {

    public $apiKey;
    public $siteId;

    /**
     * Default options
     * @var array
     */
    protected $defaultOptions = array(
        'user_id',
        //'first_name',
        //'last_name',
        'email',
        'type',
        'trigger'
    );

    protected $defaultValues = array();
    private $isSendMail = true;

    public function init() {
    }

    /**
     * Creates a customer in Customer.io
     * @param  mixed $customer_id You'll want to set this dynamically to the unique id of the user associated with the event
     * @param  array $attributes Extra customer info
     * @return void
     */
    public function createCustomer($customerId, $attributes) {
        if (!$this->isSendMail) {
            return;
        }
        $session = curl_init();
        $customerioUrl = 'https://track.customer.io/api/v1/customers/';
        curl_setopt($session, CURLOPT_URL, $customerioUrl . $customerId);
        curl_setopt($session, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($session, CURLOPT_HTTPGET, 1);
        curl_setopt($session, CURLOPT_HEADER, true);
        curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($session, CURLOPT_CUSTOMREQUEST, 'PUT');
        curl_setopt($session, CURLOPT_VERBOSE, 1);
        curl_setopt($session, CURLOPT_POSTFIELDS, http_build_query($attributes));
        curl_setopt($session, CURLOPT_USERPWD, $this->siteId . ":" . $this->apiKey);
        curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false);
        $resp = curl_exec($session);
        curl_close($session);
        if (strpos($resp, "Unauthorized request") !== false)
            throw new Exception("CustomerIo! Unauthorized request apiKey: $this->apiKey siteId: $this->siteId");
    }

    /**
     * Register an event in Customer.io
     * 
     * @param  mixed $customer_id You'll want to set this dynamically to the unique id of the user associated with the event
     * @param  string $name Event's name
     * @param  array $event_data Event data
     * @return void
     */
    public function trackEvent($customerId, $name, $eventData = array()) {
        if (!$this->isSendMail) {
            return;
        }
        $session = curl_init();
        $customerioUrl = 'https://track.customer.io/api/v1/customers/' . $customerId . '/events';
        $data = ['name' => $name, 'data' => $eventData];
        curl_setopt($session, CURLOPT_URL, $customerioUrl);
        curl_setopt($session, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        curl_setopt($session, CURLOPT_HEADER, false);
        curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($session, CURLOPT_VERBOSE, 1);
        curl_setopt($session, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($session, CURLOPT_POSTFIELDS, http_build_query($data));
        curl_setopt($session, CURLOPT_USERPWD, $this->siteId . ":" . $this->apiKey);
        curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false);
        $resp = curl_exec($session);
        curl_close($session);
    }

    /**
     * Checking for required fields
     * 
     * @param array $options user data
     * @param array $defaultFields required fields
     * @return type
     * @throws HttpException
     */
    protected function testDefaultOptions($options, $defaultFields = array()) {
        if (!$this->isSendMail) {
            return;
        }
        $createCustomerOptions = array();
        if (empty($defaultFields)) {
            $defaultFields = $this->defaultOptions;
        }
        foreach ($defaultFields as $defaultField) {
            if (!isset($options[$defaultField])) {
                throw new HttpException(501, __CLASS__ . ' no default field [' . $defaultField . ']');
            }
            if (!in_array($defaultField, ['trigger', 'user_id'])) {
                $createCustomerOptions[$defaultField] = $options[$defaultField];
            }
            if (isset($this->defaultValues[$defaultField])) {
                $createCustomerOptions[$defaultField] = $this->defaultValues[$defaultField];
            }
        }
        return $createCustomerOptions;
    }

    /**
     * Send Mail
     * 
     * @param array $options
     * @param array $createCustomerOptions
     * @return type
     * @throws Exception
     */
    protected function send($options, $createCustomerOptions = array()) {
        if (!$this->isSendMail) {
            return;
        }
        if (empty($createCustomerOptions)) {
            $createCustomerOptions = $this->defaultOptions;
        }
        try {
            $createCustomerOptions = $this->testDefaultOptions($options, $createCustomerOptions);
        } catch (Exception $e) {
            throw $e;
        }
        if (!isset($options['created_at']) || empty($options['created_at'])) {
            $options['created_at'] = time();
        }
        $this->createCustomer($options['user_id'], $createCustomerOptions);
        $this->trackEvent($options['user_id'], $options['trigger'], $options);
    }

    public function sendMail($options = array()) {
        $this->send($options);
    }

}

Add the extension and its settings in file protected/config/main.php:

//...
    'components'=>array(
        //...
        'customerio' => array(
            'class' => 'ext.customerio.CustomerIO',
            'siteId' => '<YOUR SITE ID>',
            'apiKey' => '<YOUR API KEY>',
        ),
    ),
//...

Change siteId and apiKey on their own and start to use it. Example:

Yii::app()->customerio->sendMail(
    array(
        'first_name' => 'FirstName',
        'last_name' => 'LastName',
        'email' => 'example@example.com',
        'user_id' => '1',
        'trigger' => 'test',
        'type' => 'event'
    )
);

Or add a method to the class:

public function testSend($data = array()) {
        //...
        $options = array(
            'trigger' => 'test',            
            'type' => 'event',
            'first_name' => 'FirstName',
            'last_name' => 'LastName',
            'email' => 'example@example.com',
            'user_id' => '1',
            //...
        );
        $this->send($options);
    }

Call it in the right place as follows::

Yii::app()->customerio->testSend($data);

For those who work with Yii2, remake this class will not be difficult.