segment-boneyard / analytics-magento

[DEPRECATED] The hassle-free way to integrate analytics into any Magento store.
15 stars 19 forks source link

Identify on every page #64

Closed sperand-io closed 9 years ago

sperand-io commented 10 years ago

Currently, we're only calling identify on the login or signup events (from what I can tell? - please correct me if I'm wrong :).

A segment implementation best practice is to call identify on every page load if there is a signed-in user present. That way, if a customer clicks an email link to their shopping cart that signs them in automatically, or if a customer returns to the store and their session is still active, we'll have all their traits cached in analytics.js to pass with subsequent track and page calls.

TLDR: We should call identify conditionally right above page in the snippet if there is a logged in user present.

@astorm cc @ianstormtaylor

astorm commented 10 years ago

Chris, if I remember the development cycle correctly, @ianstormtaylor specifically asked that identity not be called on every page. The first identity call is/was supposed to be enough to identify future requests. Not sure if that's changed, but check in with @ianstormtaylor and he'll set you straight.

sperand-io commented 10 years ago

Will do! Thanks Alan!

On Sun, Oct 12, 2014 at 8:22 PM, astorm notifications@github.com wrote:

Chris, if I remember the development cycle correctly, @ianstormtaylor https://github.com/ianstormtaylor specifically asked that identity not be called on every page. The first identity call is/was supposed to be enough to identify future requests. Not sure if that's changed, but check in with @ianstormtaylor https://github.com/ianstormtaylor and he'll set you straight.

— Reply to this email directly or view it on GitHub https://github.com/segmentio/analytics-magento/issues/64#issuecomment-58840067 .

tonyoconnell commented 10 years ago

Hello. We auto login our visitors when they click links in our email newsletter. That means they don't pass through the login page and therefore are not identified. I added this code to every page but it seemed to cause confusion ... i.e. it tracked multiple people as the same person. Is this related to the issue? Any idea of a work around?

<script type="text/javascript">
  analytics.identify('<?php
 if(Mage::getSingleton('customer/session')->isLoggedIn()) {
     $customerData = Mage::getSingleton('customer/session')->getCustomer();
      echo $customerData->getId();
 }
 ?>', {
  name: '<?php
 if(Mage::getSingleton('customer/session')->isLoggedIn()) {
     $customerData = Mage::getSingleton('customer/session')->getCustomer();
      echo $customerData->getName();
 }
 ?>',
  email: '<?php
 if(Mage::getSingleton('customer/session')->isLoggedIn()) {
     $customerData = Mage::getSingleton('customer/session')->getCustomer();
      echo $customerData->getEmail();
 }
 ?>'
});
</script>
'''
astorm commented 10 years ago

@tonyoconnell I helped Segment build the original extension — I'm not sure how their API works now, but at the time the identity calls needed to happen only at the time of login. Based on your description of the problem, I'm betting that still the case. So, step one would be to undo whatever changes you've done, as they seem to have created a bunch of undesired behavior.

Step 2: How does your auto login feature work? The segment extension was built with Magento best practices in mind, and listens for a customer_login event dispatch. When this event fires the segment extensions takes the necessary step to add an identity call to the page. My guess is your auto login code doesn't include this event. (It's a common oversight, Magento Inc. hasn't been the best at providing proper guidance here)

If you modify your auto login custom code to include the following (where customer is an instance of the customer object)

Mage::dispatchEvent('customer_login', array('customer'=>$customer));

Then you should be all set.

@sperand-io A possible feature for your road would be providing some sort of auto login URL so customers don't need to provider their own.

Good luck guys!

tonyoconnell commented 10 years ago

Hello Alan,

Thanks for your quick reply. The auto login works by generating a token for each customer that's appended to the URL e.g. http://example.com/?c=123343453453466 When the URL is accessed the customer that's connected to the token is logged in.

You are correct there is no customer login event dispatch in the module. I've been searching for the place I could add it and guess it's in a file called Observer.php so I tried adding the dispatch event in a few areas of the file and failed. I've attached the file. Is this the correct one? If not is there something I could search for to find it?

Best wishes,

Tony

<?php
/**
 * Autologin
 *
 * @category    Partikule
 * @package     Partikule_Autologin
 * @author      Partikule Dev Team <dev@partikule.net>
 * @copyright   Partikule (http://partikule.net)
 *
 */
class Partikule_Autologin_Model_Observer extends Mage_Core_Model_Abstract
{
    var $_updated = 0;

    /**
     * Do the Autologin at frontend
     *
     */
    public function doAutologin()
    {
        // Mage::log('Partikule_Autologin_Model_Observer > doAutologin()', null, 'partikule.log');

        if (Mage::helper('autologin')->is_module_enabled())
        {
            $session = Mage::getSingleton('customer/session');
            $request = Mage::app()->getRequest();

            $hash = $request->getParam(Mage::helper('autologin')->get_url_param_segment());

            if ( ! empty($hash))
            {
                $csv = Mage::helper('autologin')->decrypt($hash);
                $_customerinfo = explode(';', $csv);

                $customer = Mage::getModel('customer/customer')->load((int)$_customerinfo[0]);

                if ( ! $customer->getId() || $customer->getEmail() != trim($_customerinfo[1]))
                {
                    // $session->addError('User invalid or does not exist');
                    $session->logout();
                }
                else{
                    // Logout
                    $session->logout();

                    // Login
                    $session->setCustomer($customer);
                }
            }
        }
    }

    public function updateCustomer($id)
    {
        try
        {
            $_customer = Mage::getModel('customer/customer')->load($id);

            $hash = Mage::helper('autologin')->encrypt($_customer);
            $_customer->setData('login_hash', $hash)->getResource()->saveAttribute($_customer, 'login_hash');
        }
        catch(Exception $e)
        {
            return $e->getMessage();
        }
    }

    /**
     * Updates all customers hashes
     * Uses not more than 2M...
     *
     * @return int
     */
    public function updateAllCustomers()
    {
        // Mage::log('Partikule_Autologin_Model_Observer > updateAllCustomers()', null, 'partikule.log');
        $start_memory = memory_get_usage();

        $customersCollection = Mage::getModel('customer/customer')->getCollection();

        Mage::getSingleton('core/resource_iterator')->walk(
            $customersCollection->getSelect(),
            array(array($this, 'customerCallback')),
            array('start_memory' => $start_memory)
        );

        // $mem = memory_get_usage() - $start_memory;
        // Mage::log('Autologin Init Memory Use (End) : ' . $this->_updated . ' users : ' . $mem, null, 'partikule.log');

        return $this->_updated;
    }

    /**
     * Callback for customers hash update
     *
     * @param $args
     */
    public function customerCallback($args)
    {
        $_customer = Mage::getModel('customer/customer');
        $_customer->setData($args['row']);
        // $start_memory = $args['start_memory'];

        $hash = Mage::helper('autologin')->encrypt($_customer);
        $_customer->setData('login_hash', $hash)->getResource()->saveAttribute($_customer, 'login_hash');

        $this->_updated += 1;

        // $mem = memory_get_usage() - $start_memory;
        // Mage::log('Autologin Init Memory Use : ' . $mem, null, 'partikule.log');
    }

    public function saveCustomer($observer)
    {
        // Mage::log('Partikule_Autologin_Model_Observer > saveCustomer()', null, 'partikule.log');

        $customer = $observer->getCustomer();

        $hash = Mage::helper('autologin')->encrypt($customer);

        $customer->setData('login_hash', $hash)->getResource()->saveAttribute($customer, 'login_hash');
    }
}
astorm commented 10 years ago

@tonyoconnell The folks to be asking that questions are the ones who wrote the Partikule_Autologin module for you. I don't see any calls to a login or authenticate function in the file you posted, so that's probably not the place. Although there may not be such a method, as mentioned your auto login code is completely custom -- without a Magento developer doing a short consulting gig there's no way to know for sure how the autologin was/is implemented. There's myriad ways to accomplish that.

Also, it may be possible you were dispatching the event in the correctly place, but with a not fully populated customer object.

Also, it may be possible you were dispatching the event in the right place, but an additional customization done to you system prevented the observer from adding the identity block.

I'd start by using an exit(__METHOD__); to identify where the login happens. Then, add the event dispatch. Then debug why the identity call isn't added to the page.

Sorry I can't be more helpful, but it's not always so straight forward with a Magento system using custom programming -- maybe @sperand-io can dig into this more for you.

Good luck!

tonyoconnell commented 10 years ago

@astorm Thanks.

tonyoconnell commented 10 years ago

Hello. I'm wondering what we should do to identify customers that are already logged in before we installed Segment's Magento module.

ianstormtaylor commented 10 years ago

Definitely, that seems like a good reason for us to identify on all pages where the user is currently logged in. @astorm is right that we had chosen not to do that originally. I don't remember our thought process from back then (can't find any issues related to it), but I think we were wrong to assume that.

So it looks like calling identify on every page is the preferred logic. What do you think @sperand-io?

reinpk commented 9 years ago

+1 identifying everywhere is the best practice we promote in general, and solves some key use cases for email marketing, which is a huge channel for all the ecommerce companies i've spoken to.

sperand-io commented 9 years ago

Fixed :)