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:
- Create a new observer in your module:
- Register observer in config.xml
- Create observer method
- 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:
- 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.
Adding Consent Checkboxes Manually
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.