Magento 1 GDPR v1.x Developer Guide and API Reference

In this developer documentation for the Magento GDPR & CCPA Extension, you will find step-by-step instructions, sample code, and API references to fully customize your plugin.

Downloading, Deleting and Anonymizing Customer Data

Plumrocket GDPR Magento 1 extension allows you to manage any third-party data stored in your Magento database. Use this manual to make your third-party extension GDPR compliant. Contact vendors of the third-party extensions you are using, and ask them if their extensions record any personal customer data in your Magento database. If they collect any personal data, they may become GDPR compliant by integrating their plugins with Plumrocket GDPR Extension using the provided API.

Export, delete or anonymize third-party data in 2 simple steps:

  1. Create a new observer in your module:
    1. Register observer in config.xml
    2. Create observer method
  2. Create GDPR model in the third-party plugin to manage your customer data.

Step 1. Create a New Observer in Your Module

a) Register observer in config.xml file.

Open the file:

/app/code/community/VendorName/ModuleName/etc/config.xml

and add the code as shown below (or download the template here.):

<global>
    <events>
        <prgdpr_processors_collect_after>
            <observers>
                <observer_name>
                    <type>singleton</type>
                    <class>groupedClassName/observerModelName</class>
                    <method>prgdprProcessorsCollectAfter</method>
                 </observer_name>
            </observers>
        </prgdpr_processors_collect_after>
    </events>
</global>

b) Create observer method

Your observer method must receive one argument – $observer with instance of Plumrocket_GDPR_Model_AbstractGdprTool in it.

Method Plumrocket_GDPR_Model_AbstractGdprTool::addProcessorWithSort can have 3 arguments:

  • “$processor” – “GDPR” model that should process all data (export / anonymize / delete)
  • “[$sort]” – describes the sort position of each GDPR model defined in $sortValue. Allowed values: “before”, “after”. Default value is “before”.
  • “[$sortValue]” – Key name of your GDPR model which is used in sorting. Allowed values: Key name of GDPR model (example: “order”) or use dash (-) to position your GDPR model before/after all other models in the list. Default value is “customer”.

Please note: The last two arguments are not required. They are useful when you need to specify the order in which your GDPR model must be executed. Example: let’s say you have 3 GDPR models with key names – “myCustomGDPRmodel”, “order” and “customer”. You can set the execution position of these models and specify that “myCustomGDPRmodel” should be executed after the “customer” model.

Example:

$tool->addProcessorWithSort($myCustomGDPRmodel, ‘after’, ‘customer’);

Now let’s create our observer method.

Open or create file:

/app/code/community/VendorName/ModuleName/Model/ObserverModelName.php

Add method prgdprProcessorsCollectAfter() and add the code as shown below (or download the template here.):

/**
 * @param Varien_Event_Observer $observer
 * @return void
 */
public function prgdprProcessorsCollectAfter($observer)
{
    /** @var VendorName_ModuleName_Model_ProcessorModelName $processor */
    $processor = Mage::getModel('groupedClassName/processorModelName');

    /** @var Plumrocket_GDPR_Model_AbstractGdprTool $tool */
    $tool = $observer->getTool();

    $tool->addProcessorWithSort($processor, ‘before’, ‘customer’);
}


Step 2. Create GDPR Model

Create your class “VendorName_ModuleName_Model_Gdpr_Processor” that extends Plumrocket_GDPR_Model_AbstractProcessor.

Class Plumrocket_GDPR_Model_AbstractProcessor has the following methods:

  • _anonymize(Mage_Core_Model_Abstract $model)
  • _erase(Mage_Core_Model_Abstract $model)
  • _export(Varien_Object $model)
  • _massExport($models)
  • _massAnonymize(array $models, callable $callback = null)
  • _massErase(array $models, callable $callback = null)

Please note: $callback – is a function executed for each model before mass erasure or anonymization.

function getMapping() defines which data will be anonymized or exported.

Where:

“db_field_name1” is the name of the database field or attribute code that should be anonymized or exported:

Data anonymization options:

  • Array Key (bool) “anonymize” defines whether field should be anonymized or not. Default value is “true”.
  • Array Key (string) “default” – replaces field value with your string value. if nothing is defined, [Anonymization Key] + “-” + [Customer Id] will be set instead.Please note: the “Anonymization Key” can be set in Magento System Configuration -> GDPR -> Account Removal Settings -> Anonymization Key.

Data export options:

  • Array Key (bool) “export” defines whether field should be exported or not. Default value is “true”.
  • Array Key (string) “title” allows you to rename “db_field_name1” column in the CSV file. Default value is a result of the function uc_words( “db_field_name1” ).
  • Array Key (callable) “decorator” – anonymous function allows you to define custom format of the field “db_field_name1” before it’s exported to the CSV file. This function can receive two arguments – value of the “db_field_name1” and the current model. Example of the code below allows you to format Order Grand Total using our anonymous function:
'decorator' => function ($value, $order) {
    return $order>getOrderCurrency()->formatPrecision($value, 2, array(), false);
},

Lastly, if you provide empty array of options, (see ‘ db_field_name2′ in example below), the default values will be set.

Now, let’s create GDPR Model file:

/app/code/pool/VendorName/ModuleName/Model/Gdpr/Processor.php

and add the code as shown below (or download the template here.):

class VendorName_ModuleName_Model_Gdpr_Processor extends Plumrocket_GDPR_Model_AbstractProcessor implements Plumrocket_GDPR_Model_ProcessorInterface
{
    public function getKey()
    {
        return 'unique_key'; // unique key of your GDPR model
    }

    public function getModuleName()
    {
        return 'VendorName_ModuleName';
    }

    public function getPublicFilename()
    {
        return 'your_filename'; // your CSV file name
    }

    /**
     * @return array
     */
    public function getMapping()
    {
        return array(
            'db_field_name1' => array(
                // data anonymization options
                ‘anonymize’ => bool,
                'default' => string,
                // data export options
                'export' => bool,
                ‘title’ => string,
                ‘decorator’ => callable
            ),
            'db_field_name2' => array(),
            'db_field_name3' => array(
                'export' => bool,
                ‘title’ => string,
                ‘decorator’ => callable
            )
        );
    }

    /**
     * @param Mage_Customer_Model_Customer $customer
     * @return bool
     */
    public function anonymize($customer)
    {
        $collection = $this->_getCollectionByCustomer($customer);

        return $this->_massAnonymize($collection);
    }

    /**
     * @param Mage_Customer_Model_Customer $customer
     * @return bool
     */
    public function erase($customer)
    {
        $collection = $this->_getCollectionByCustomer($customer);

        return $this->_massErase($collection);
    }

    /**
     * @param Mage_Customer_Model_Customer $customer
     * @return bool
     */
    public function export($customer)
    {
        $collection = $this->_getCollectionByCustomer($customer);

        return $this->_massExport($collection);
    }

    /**
     * @param Mage_Customer_Model_Customer $customer
     * @return Mage_Core_Model_Abstract[]
     */
    protected function _getCollectionByCustomer($customer)
    {
        /** @var Mage_Core_Model_Resource_Db_Collection_Abstract $collection */
        $collection = Mage::getModel('groupedClassName/entity_name')->getCollection();
        $collection->addFieldToFilter('customer_id', $customer->getId());

        return $collection->getItems();
    }
}

Example

This example is based on Free Plumrocket Twitter & Facebook Login Extension for Magento 1. You can download it from our store for your reference.

Step 1.a “config.xml” file of Plumrocket Twitter & Facebook Login Extension

1.a) Observer in config.xml file Open the file:

/app/code/community/Plumrocket/SocialLogin/etc/config.xml
<global>
    <events>
        <prgdpr_processors_collect_after>
            <observers>
                <pslogin_observer>
                    <type>singleton</type>
                    <class>pslogin/observer</class>
                    <method>prgdprProcessorsCollectAfter</method>
                </pslogin_observer>
            </observers>
        </prgdpr_processors_collect_after>
    </events>
</global>

Step 1.b “Observer.php” file of Plumrocket Twitter & Facebook Login Extension

1.b) Observer method Open the file:

/app/code/community/Plumrocket/SocialLogin/Model/Observer.php
/**
 * @param Varien_Event_Observer $observer
 * @return void
 */
public function prgdprProcessorsCollectAfter($observer)
{
    /** @var Plumrocket_SocialLogin_Model_Gdpr_Processor $processor */
    $processor = Mage::getModel('pslogin/gdpr_processor');

    /** @var Plumrocket_GDPR_Model_AbstractGdprTool $tool */
    $tool = $observer->getTool();

    $tool->addProcessorWithSort($processor);
}

Step 2. GDPR Model of Plumrocket Twitter & Facebook Login Extension

File path:

/app/code/community/Plumrocket/SocialLogin/Model/Gdpr/Processor.php
class Plumrocket_SocialLogin_Model_Gdpr_Processor extends Plumrocket_GDPR_Model_AbstractProcessor
{
    const KEY = 'pslogin';

    /**
     * @return string
     */
    public function getKey()
    {
        return self::KEY;
    }

    /**
     * @return string
     */
    public function getPublicFilename()
    {
        return 'social_accounts';
    }

    /**
     * @return string
     */
    public function getModuleName()
    {
        return 'Plumrocket_SocialLogin';
    }

    /**
     * @return array
     */
    public function getMapping()
    {
        return array(
            'type' => array(
                'title' => 'Social network',
                'anonymize' => false
            ),
            'user_id' => array(
                'title' => 'Id in social network'
            ),
            'photo' => array(
                'title' => 'Photo',
                'decorator' => $this->getPhotoDecorator()
            )
            // In this case, photo is not a db field, its created by our "decorator" - anonymous function using helper and model
        );
    }

    /**
     * @param Mage_Customer_Model_Customer $customer
     * @return bool
     */
    public function anonymize($customer)
    {
        return $this->_massAnonymize($this->getSocialAccounts($customer), $this->getRemovePhotoCallback());
    }

    /**
     * @param Mage_Customer_Model_Customer $customer
     * @return bool
     */
    public function erase($customer)
    {
        return $this->_massErase($this->getSocialAccounts($customer), $this->getRemovePhotoCallback());
    }
    // $this->getRemovePhotoCallback() - is used to remove profile photo. Returns function that will be called before anonymization/erasure procedure and will delete the picture file.

    /**
     * @param Mage_Customer_Model_Customer $customer
     * @return array|null
     */
    public function export($customer)
    {
        return $this->_massExport($this->getSocialAccounts($customer));
    }

    /**
     * @param Mage_Customer_Model_Customer $customer
     * @return array
     */
    protected function getSocialAccounts($customer)
    {
        /** @var Plumrocket_SocialLogin_Model_Mysql4_Account_Collection $collection */
        $collection = Mage::getResourceModel('pslogin/account_collection');
        $collection->addFieldToFilter('customer_id', $customer->getId());

        return $collection->getItems();
    }

    /**
     * @return Closure
     */
    private function getRemovePhotoCallback()
    {
        $io            = new Varien_Io_File();
        /** @var Plumrocket_SocialLogin_Helper_Data $psLoginHelper */
        $psLoginHelper = Mage::helper('pslogin');
        /** @var Plumrocket_GDPR_Helper_Data $gdprHelper */
        $gdprHelper    = Mage::helper('prgdpr');

        /**
         * @param Plumrocket_SocialLogin_Model_Account $model
         */
        $removePhotoCallback = function($model) use ($io, $psLoginHelper, $gdprHelper)
        {
            $photo = $psLoginHelper->getAbsolutePhotoPath($model->getCustomerId());
            if ($photo) {
                if (!$io->rm($photo)) {
                    $gdprHelper->logError('Unlink file ' . $photo . ' failed');
                }
            }

            $photo = $psLoginHelper->getAbsolutePhotoPath($model->getCustomerId(), $model->getType());
            if ($photo) {
                if (!$io->rm($photo)) {
                    $gdprHelper->logError('Unlink file ' . $photo . ' failed');
                }
            }
        };

        return $removePhotoCallback;
    }

    /**
     * @return Closure
     */
    private function getPhotoDecorator()
    {
        return function($photo, $model)
        {
            /** @var Plumrocket_SocialLogin_Model_Account $model */
            $photo = Mage::helper('pslogin')->getPhotoPath(false, $model->getCustomerId(), $model->getType());

            if (!$photo) {
                $photo = $model->getAccountImage();
            }

            return $photo;
        };
    }
}

GDPR Developer’s FAQ:

  1. How do I change the default Magento 1 GDPR config?Edit files in folder:
/app/code/community/Plumrocket/GDPR/Model/Processor

2. Can I anonymize all data instead of deleting it?Yes, you can. In order to enable or disable the erasure/anonymization, you must set the value returned by the method isEraseMode in file

/app/code/community/Plumrocket/GDPR/Helper/Config.php

to “false”.

However, please note, that you can only enable the anonymization for a part of data, see more details below:

Data that can be erased or anonymized:

  • customer_address
  • customer_information
  • customer_log
  • log_of_account_removal_requests
  • reviews

Data that is always erased:

  • price_and_stock_alerts
  • compare_products
  • email_in_queue
  • enterprise_customerbalance
  • enterprise_giftregistry
  • enterprise_giftregistry_person
  • enterprise_invitation
  • enterprise_reward
  • log_of_account_data_downloads
  • log_of_customer_consents
  • order_gift_messages
  • poll_vote
  • addresses_saves_in_cart
  • cart_information
  • cart_flat
  • products_in_cart
  • forgot_password
  • newsletter_subscriber
  • rating
  • wishlist

Data that is always anonymized:

  • archive_order
  • archive_creditmemo
  • archive_invoice
  • archive_shipment
  • enterprise_rma
  • order_addresses
  • order_information

3. I have implemented the GDPR support in my third-party extension, can I share it with you? Yes, absolutely. We can add the built-in support of the third-party extension to our GDPR module after we review your code. Please contact our tech support and submit your request.

4. What data and Magento tables are affected by the GDPR extension? During download, deletion or anonymization process, the following database tables are affected:

Magento 1.x Community Edition (CE)Magento 1.x Enterprise Edition (EE)
customer_entity
customer_entity
customer_entity_*
product_alert_price
product_alert_stock
core_email_queue_recipients
customer_flowpassword
customer_address_entity
customer_address_entity_*
review
review_detail
wishlist
wishlist_item
catalog_compare_item
newsletter_subscriber
poll_vote
poll_answer
rating_option_vote
log_quote
log_url
log_visitor
log_visitor_info
log_customer
sales_flat_order
sales_flat_order_address
sales_flat_order_grid
sales_flat_order_item
gift_message
sales_flat_quote
sales_flat_quote_address
plumrocket_gdpr_consent
plumrocket_gdpr_eraser_log
plumrocket_gdpr_exporter_log
customer_entity
customer_entity_*
product_alert_price
product_alert_stock
customer_address_entity
customer_address_entity_*
review
review_detail
wishlist
wishlist_item
catalog_compare_item
newsletter_subscriber
poll_vote
poll_answer
rating_option_vote
log_quote
log_url
log_visitor
log_visitor_info
log_customer
sales_flat_order
sales_flat_order_address
sales_flat_order_grid
sales_flat_order_item
gift_message
sales_flat_quote
sales_flat_quote_address
enterprise_rma
enterprise_rma_grid
enterprise_rma_item_entity
enterprise_rma_item_entity_*
enterprise_giftregistry_entity
enterprise_giftregistry_person
enterprise_sales_order_grid_archive
enterprise_sales_creditmemo_grid_archive
enterprise_sales_invoice_grid_archive
enterprise_sales_shipment_grid_archive
enterprise_customerbalance
enterprise_invitation
enterprise_reward
plumrocket_gdpr_consent
plumrocket_gdpr_eraser_log
plumrocket_gdpr_exporter_log

See Magento Magento DevDocs for more information about the Magento 1.x GDPR compliance and data storage.

Use the documentation below to manually place checkboxes in the needed location of the page. At the moment 3 checkbox locations are supported: registration, checkout or newsletter subscription forms.

Please note, you must first add the “Consent Checkboxes” in the Magento System Configuration -> GDPR -> Consent Checkboxes. See wiki configuration page for more details.

Example 1. Displaying Checkboxes Using Structural Blocks

If your page is built using structural blocks (core/text_list blocks), then you should use the code from the example below.

In this example we will add checkboxes on the Registration Page. Add structural block to the XML layout file:

Open the file:

/app/design/frontend/base/default/layout/your_module_layout_file.xml

and add the code as shown below:

<reference name="form.additional.info">
    <block type="prgdpr/checkboxes" name="prgdpr.register.checkbox">
        <action method="setTemplate" ifconfig="prgdpr/general/enable">
            <template>prgdpr/form/checkbox.phtml</template>
       </action>
       <action method="setType"><type>register</type></action>
    </block>
</reference>

Where:“type” argument describes the type of the checkbox. E.G:

<action method="setType"><type>PageType</type></action>

“PageType” can have the following values: “register”, “newsletter” or “checkout”.

Example 2. Displaying Checkboxes Using Layout Blocks

Create layout blocks (core/template) if you need to add checkboxes within HTML content. Use the code from the example below.

In this example we will add checkboxes into the Newsletter Subscription form.

Open the file:

/app/design/frontend/base/default/template/newsletter/subscribe.phtml

and add the highlighted code as shown below:

<div class="block block-subscribe">
 <div class="block-title">
 <strong><span><?php echo $this->__('Newsletter') ?></span></strong>
 </div>
 <form action="<?php echo $this->getFormActionUrl() ?>" method="post" id="newsletter-validate-detail">
 <div class="block-content">
 <div class="form-subscribe-header">
 <label for="newsletter"><?php echo $this->__('Sign Up for Our Newsletter:') ?></label>
 </div>
 <div class="input-box">
 <input type="text" name="email" id="newsletter" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Sign up for our newsletter')) ?>" class="input-text required-entry validate-email" />
 </div>
 <div class="actions">
 <button type="submit" title="<?php echo Mage::helper('core')->quoteEscape($this->__('Subscribe')) ?>" class="button"><span><span><?php echo $this->__('Subscribe') ?></span></span></button>
 </div>
 </div>
 <div class="prgdpr-newsletter-checkboxes-container"></div>
 <script>
 pjQuery_1_12_4(document).ready(function($) {
 $.get('<?php echo $this->getUrl('prgdpr/newsletter/html') ?>', function (data) {
 $('.prgdpr-newsletter-checkboxes-container').each(function (index, elem) {
 $(elem).html(data);
 });
 })
 });
 </script>
 </form>
 <script type="text/javascript">
 //<![CDATA[
 var newsletterSubscriberFormDetail = new VarienForm('newsletter-validate-detail');
 //]]>
 </script>
</div>

Displaying Checkboxes On Checkout Page

Plumrocket GDPR extension uses native Magento functionality of “Terms and Conditions” (Agreements) to display GDPR consent checkboxes on checkout page. This allows you to stay compatible with majority of third party extensions. Consent validation and logging also replicates this functionality. In order to display GDPR checkboxes make sure that your third party checkout extension supports native Magento “Terms and Conditions”.

Go to your “Magento Admin -> Sales -> Terms and Conditions” to view this functionality.

Blocking non-essential Cookies

Plumrocket GDPR extension uses the native Magento “Cookie Restriction Mode” functionality to display Cookie Restriction Notice Block. It allows you to block all non-essential cookies until visitor consent is given. Only after the visitor consent is given (eg: “Allow Cookies” button is pressed), the non-essential cookies will be created.

According to GDPR, non-essential cookies, such as those used for analytics, cookies from advertisers or third parties, including affiliates and those that identify a user when he returns to the website should not be used until the consent is provided.

If your JavaScript code creates cookies, you can block it from execution, until the customer consent is given. To do so, copy the code below and insert your JavaScript in the highlighted section:

Copy File:

/app/design/frontend/base/default/template/prgdpr/cookie/alert.phtml

To the folder with your Magento theme:

/app/design/frontend/rwd/default/template/prgdpr/cookie/alert.phtml

Where “rwd>/default” is the name of your theme name / package name

Then add/edit the following code:

<?php if ($this->isAllowGtm()) : ?>
    <script type="text/javascript">
        var gtm_tag = document.createElement('script');
        gtm_tag.type = 'text/javascript';
        gtm_tag.text = '(function(w,d,s,l,i){w[l]=w[l]||[];
        w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});
        var f=d.getElementsByTagName(s)[0],j=d.createElement(s),
        dl=l!='dataLayer'?'&l='+l:'';j.async=true;j
        .src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
        f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer',
            '<?php echo $this->getGtmContainerId(); ?>');';
        document.body.appendChild(gtm_tag);
 
    // Add your js code here
    </script>
<?php endif; ?>

Developer’s Guide for GeoIP Functionality

Plumrocket GDPR extension comes bundled with Plumrocket GeoIP Lookup extension . This add-on is used to identify customer’s location from IP and deliver targeted content. With this plugin enabled, GDPR can be configured to display cookie restriction notice and consent checkboxes only for visitors from EU countries or custom list of countries. Learn more about GeoIP Rest API and other methods of retrieving customer location here – Magento GeoIP Lookup Developers Guide and API Reference.

Was this article helpful?