Developed with love by KnpLabs Hire us for your project!
31

GordalinaMixpanelBundle

by gordalina

Symfony bundle for Mixpanel

GordalinaMixpanelBundle

Build Status

Integration of the Mixpanel library
into Symfony.

Installation

Require gordalina/mixpanel-bundle using composer

$ php composer.phar require gordalina/mixpanel-bundle:~3.0

Or require
gordalina/mixpanel-bundle
to your composer.json file:

{
    "require": {
        "gordalina/mixpanel-bundle": "~3.0"
    }
}

Register the bundle in config/bundles.php:

// config/bundles.php
    return [
        // ...
        Gordalina\MixpanelBundle\GordalinaMixpanelBundle::class => ['all' => true],
    ];
}

Enable the bundle's configuration in app/config/config.yml:

# app/config/config.yml

gordalina_mixpanel:
    projects:
        default:
            token: xxxxxxxxxxxxxxxxxxxx

Usage

This bundle registers a gordalina_mixpanel.default, mixpanel.default and mixpanel
service which is an instance of Mixpanel (from the official library).
You'll be able to do whatever you want with it.

NOTE: This bundle sends your client's ip address automatically. If you have
a reverse proxy in you servers you should set it in your front controller public/index.php:

// public/index.php
Request::setTrustedProxies(
    // the IP address (or range) of your proxy
    ['192.0.0.1', '10.0.0.0/8'],
    Request::HEADER_X_FORWARDED_ALL
);

You can find more documentation on Symfony website: How to Configure Symfony to Work behind a Load Balancer or a Reverse Proxy

Killer Feature

Track an event with a single annotation

<?php
// CheckoutController.php

use Gordalina\MixpanelBundle\Annotation as Mixpanel;

class CheckoutController
{
    /**
     * @Mixpanel\Track("View Checkout")
     */
    public function view(Request $request)
    {
        // ...
    }

Sending people information to Mixpanel

Mixpanel allows you to track your user's behaviours, but also some user information.
When using annotations which require the distinct_id,
this will be set automatically. This is done automatically provided you have configured it properly.
You are able to override this value if you wish.

# config/packages/gordalina_mixpanel.yaml

gordalina_mixpanel:
    projects:
        default:
            token: xxxxxxxxxx
    users:
        Symfony\Component\Security\Core\User\UserInterface:
            id: username
            email: email

        # All possible properties
        YourAppBundle\Entity\User:
            id: id
            first_name: first_name
            last_name: last_name
            email: email
            phone: phone
            extra_data:
                - { key: whatever, value: test }

This bundle uses property access to get the values out of the user object, so
event if you dont have a first_name property, but have a getFirstName method
it will work.

NOTE: extra_data corresponding non-default properties in Mixpanel user profile

<?php
// UserController.php

use Gordalina\MixpanelBundle\Annotation as Mixpanel;

class UserController
{
    /**
     * @Mixpanel\UpdateUser()
     */
    public function userUpdated(User $user, Request $request)
    {
        // ...
    }

In the following example, we call UpdateUser, which sends all information registered
in the configuration above, but we override the id property with an expression
that evaluates the user id.
The @Expression annotation uses ExpressionLanguage
for evaluation.

<?php
// OrderController.php

use Gordalina\MixpanelBundle\Annotation as Mixpanel;

class OrderController
{
    /**
     * @Mixpanel\Track("Order Completed", props={
     *      "user_id": @Mixpanel\Expression("user.getId()")
     * })
     * @Mixpanel\TrackCharge(
     *      id=324"),
     *      amount=@Mixpanel\Expression("order.getAmount()")
     * )
     */
    public function orderCompleted(Order $order, Request $request)
    {
        // ...
    }

Annotations

Mixpanel Actions

Events
- @Mixpanel\Register(prop="visits", value=3)
- @Mixpanel\Track(event="name", props={ "firstTime": true })
- @Mixpanel\Unregister(prop="email")

Engagement
- @Mixpanel\Append(id=324, prop="fruits", value="apples" [, ignoreTime=false])
- @Mixpanel\ClearCharges(id=324 [, ignoreTime=false])
- @Mixpanel\DeleteUser(id=324 [, ignoreTime=false])
- @Mixpanel\Increment(id=324, prop="visits", value=3 [, ignoreTime=false])
- @Mixpanel\Remove(id=324, prop="email")
- @Mixpanel\Set(id=324, props={ "firstTime": true } [, ignoreTime=false])
- @Mixpanel\SetOnce(id=324, props={ "firstTime": true } [, ignoreTime=false])
- @Mixpanel\TrackCharge(id=697, amount="20.0" [, ignoreTime=false])

Custom Annotations

  • @Mixpanel\Id()
  • @Mixpanel\Expression(expression="<expression>")
  • @Mixpanel\UpdateUser()

Note: The first argument is not required to specify the name explicitly,
e.g: @Mixpanel\Expression("<expression>") or @Mixpanel\Set("<property>", value="<value>").

Note: All id properties can be omitted, as they will be set with the id of
the current user in security.context

MixpanelEvent

You can also send an event through symfony events when the annotations are not sufficient like this:
```php

In controller

namespace myNamespace;

use Gordalina\MixpanelBundle\Annotation as Annotation;
use Gordalina\MixpanelBundle\Mixpanel\Event\MixpanelEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

// ...

public function edit(User $user, EventDispatcherInterface $eventDispatcher, Request $request)
{
// Your code
$annotation = new Annotation\Track();
$annotation->event = 'My event';
$annotation->props = [
'prop 1' => 'data 1',
'prop 2' => 'data 2',
];

$eventDispatcher->dispatch(new MixpanelEvent($annotation, $request));
// Rest of your code

}
```

Override Props in all Annotations

In all your annotations, you can have something like this:
php
/**
* @Mixpanel\Track("Your event", props={
* "user_id": @Mixpanel\Expression("user.getId()")
* })
*/
public function yourAction()
{
// ...
}

It can be annoying to always have to put the same properties in your annotations. The functioning of the events allows us to avoid that.

namespace YourNamespace;

use Doctrine\Common\Annotations\Reader;
use Gordalina\MixpanelBundle\Annotation;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\Security\Core\Security;

class MixpanelListener
{
    private $annotationReader;
    private $security;

    public function __construct(Reader $annotationReader, Security $security)
    {
        $this->annotationReader = $annotationReader;
        $this->security         = $security; 
    }

    public function onKernelController(ControllerEvent $event)
    {
        if (!\is_array($controller = $event->getController())) {
            return;
        }

        $className = \get_class($controller[0]);
        $object    = new \ReflectionClass($className);
        $method    = $object->getMethod($controller[1]);

        $classAnnotations  = $this->annotationReader->getClassAnnotations($object);
        $methodAnnotations = $this->annotationReader->getMethodAnnotations($method);

        foreach ([$classAnnotations, $methodAnnotations] as $collection) {
            foreach ($collection as $annotation) {
                if ($annotation instanceof Annotation\Annotation && property_exists($annotation, 'props')) {
                    $annotation->props['user_id'] = $this->security->getUser()->getId();
                }
            }
        }
    }
}

And in your config:
yaml
YourNamespace\MixpanelListener:
tags:
- { name: kernel.event_listener, event: kernel.controller, method: onKernelController, priority: -200 }

Symfony Profiler Integration

Mixpanel bundle additionally integrates with Symfony2 profiler. You can
check number of events and engagements sent, total execution time and other information.

Example<br>
Toolbar

Reference Configuration

You'll find the reference configuration below:

# app/config/config*.yml

gordalina_mixpanel:
    enabled: true                                 # defaults to true
    enable_profiler: %kernel.debug%               # defaults to %kernel.debug%
    auto_update_user: %kernel.debug%              # defaults to %kernel.debug%
    projects:
        default:
            token: xxxxxxxxxxxxxxxxxxxxxxxxxxxx # required
            options:
                max_batch_size:  50               # the max batch size Mixpanel will accept is 50,
                max_queue_size:  1000             # the max num of items to hold in memory before flushing
                debug:           false            # enable/disable debug mode (logs messages to error_log)
                consumer:        curl             # which consumer to use (curl, file, socket)
                consumers:
                    custom_consumer:  ConsumerStrategies_CustomConsumConsumer # Your consumer, update above to use it
                host:            api.mixpanel.com # the host name for api calls
                events_endpoint: /track           # host relative endpoint for events
                people_endpoint: /engage          # host relative endpoint for people updates
                use_ssl:         true             # use ssl when available
                error_callback:  'Doctrine\Common\Util\Debug::dump'

        minimum_configuration:
            token: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
    users:
        Symfony\Component\Security\Core\User\UserInterface:
            id: username
            email: email

        # All possible properties
        YourAppBundle\Entity\User:
            id: id
            first_name: first_name
            last_name: last_name
            email: email
            phone: phone

Spec

In order to run the specs install all components with composer and run:

./bin/phpspec run

License

This bundle is released under the MIT license. See the complete license in the
bundle:

Resources/meta/LICENSE

Copyright (c) 2014 Samuel Gordalina <samuel.gordalina@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
gordalina_mixpanel:
enable_profiler: ~
users:

# Prototype
class:
id: ~ # Required
first_name: ~
last_name: ~
email: ~
phone: ~
projects:

# Prototype
name:
token: ~ # Required
options:
max_batch_size: ~
max_queue_size: ~
debug: ~
consumer: curl
consumers:

# Prototype
name:
class: ~ # Required
host: ~
events_endpoint: ~
people_endpoint: ~
use_ssl: ~
error_callback: ~
  • Add travis ci badge
    By web-flow, 1 month ago
  • Merge pull request #7 from Yproximite/symfony-compatibility
    By web-flow, 1 month ago
  • feat(update doc + changelog)
    By , 1 month ago
  • fix(replace Panel by panel in filename)
    By RomulusED69, 1 month ago
  • fix(rename MixPanel by Mixpanel)
    By RomulusED69, 1 month ago
  • feat(AuthentificationListener): use MixpanelEvent instead of recreate same code
    By RomulusED69, 1 month ago
  • fix(config enabled): missing auto_update
    By RomulusED69, 1 month ago
  • feat(config enabled): enable or disable sending data to mixpanel
    By RomulusED69, 1 month ago
  • feat(update readme): add all new functionalities
    By RomulusED69, 1 month ago
  • fix(travis): use php-cs-fixer min 2.16.4
    By RomulusED69, 1 month ago
  • feat(remove php7.1 support): not maintained
    By RomulusED69, 1 month ago
  • fix(composer): add composer.lock + fix version
    By RomulusED69, 1 month ago
  • fix(travis): remove symfony 4.3 not maintained
    By RomulusED69, 1 month ago
  • feat(Add travis): config travis
    By RomulusED69, 1 month ago
  • fix(php-cs-fixer)
    By RomulusED69, 1 month ago
  • fix(phpspec): rename class
    By RomulusED69, 1 month ago
  • feat(extra_data user): send non-default properties in MixPanel user profile
    By RomulusED69, 1 month ago
  • feat(autowire + event): MixPanelEvent
    By RomulusED69, 1 month ago
  • feat(prepareAnnotation with 2 levels): used Expression and Id in props
    By RomulusED69, 1 month ago
  • feat(add config auto_update_user): set user profile on each request
    By RomulusED69, 1 month ago
  • fix(ControllerListener): getId not exist
    By RomulusED69, 1 month ago
  • fix(AuthentificationListener): onKernelRequest only if master request
    By RomulusED69, 1 month ago
  • fix(kernel event_listener): bad event name
    By RomulusED69, 1 month ago
  • service injected at the wrong parent
    By tristanbes, 1 month ago
  • Symfony2 -> Symfony
    By tristanbes, 1 month ago
  • wrong class named used, it fails on case sensitive system
    By tristanbes, 1 month ago
  • flush method is not inside ManagerRegistry, but in Flusher.php
    By tristanbes, 1 month ago
  • missing use
    By tristanbes, 1 month ago
  • clear wrong doctype
    By tristanbes, 1 month ago
  • fix listeners
    By tristanbes, 1 month ago