Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pixel Opt In : EU Privacy Compliance & GDPR #301

Closed
blindpenguin opened this issue Feb 26, 2018 · 50 comments
Closed

Pixel Opt In : EU Privacy Compliance & GDPR #301

blindpenguin opened this issue Feb 26, 2018 · 50 comments
Labels
GDPR type: enhancement The issue is a request for an enhancement.

Comments

@blindpenguin
Copy link

Hello there,

i just got my new terms & conditions and was informed, that Facebook Pixel needs an opt in according to german law. Just like the european cookie notice. It isn't allowed to track anything unless the customer agrees to it.

Are there settings or something like that available for it?

Thanks

@mengyingdu
Copy link
Contributor

Hi @blindpenguin and @crudolf,

To confirm if I understood correctly, you want to opt-out (not to track user information by pixel), but still using plugin to sync product and manage your business on Facebook page, is that correct?

Thank you.

@blindpenguin
Copy link
Author

The website visitor needs to be able to opt-in. If i let facebook track users without their explicit consent, then there is the possibility to receive a cease-and-desist warning. It's only about the Pixel functionality. Everything else is fine.

One possibility could be to show a modal or notification bar. Ideally with customizeable text. Only if the visitor clicks on "yes" or "i agree", then tracking is allowed.

There is a huge post on linkedin about this, where the legal stuff is explained in detail: The regulatory pitfalls of the Facebook Pixel

@mengyingdu
Copy link
Contributor

Hi @blindpenguin and @crudolf,

Thanks for flag this. I will mark this as feature request and forward your legal concern to our pixel team.

Thank you.

@dmitridr
Copy link
Contributor

Hello,

You are correct. Our plugin did pass our own legal team and they noted the same thing. We do advise you during the setup of our plugin to seek out ways to provide this notice to users in the EU, though it's easy to miss.

euwarning

Unfortunately our plugin does not provide a consent notice in it's current functionality, but there are wordpress plugins that do provide this functionality out there, and I'd encourage you to explore using those and seeing if they can be customized to cover the case of the Facebook pixel as well.

For example just a few:
https://wordpress.org/plugins/uk-cookie-consent/
https://wordpress.org/plugins/eu-cookie-law/
https://wordpress.org/plugins/hayona-cookies/

I don't think we will ever get around to implementing this notice in our own plugin, but I will leave this open for others to jump in and recommend potential solutions (or perhaps send us a pull request).

@dmitridr
Copy link
Contributor

Just flagging, we are thinking about adding opt-out functionality based on how many users would be affected. It seems it's a great deal more than we originally thought, and it's affecting all of our plugins, not just WooCommerce. We're having some internal discussions now, I'll update if there's any news.

@dmitridr dmitridr changed the title Pixel Opt In : EU Privacy Compliance Pixel Opt In : EU Privacy Compliance & GDPR Mar 20, 2018
@dmitridr
Copy link
Contributor

dmitridr commented Mar 22, 2018

Hello All,

I have updates on this issue from the broader Facebook org on GDPR.
Specific to the FB pixel, Facebook is pursuing a solution at the user level that will require very little action for businesses who installed the pixel. There will be no need to remove the pixel, and the requirements to provide notice to users will be largely the same as they are now.

I'm not allowed to give out any details about this solution at this time, but when it becomes public I'll update this thread and close it.

www.facebook.com/business/GDPR has more information about our general policy here.

@addedlovely
Copy link
Contributor

Hi Dmitri,

Any update on this.

Thanks,

Ian.

@dmitridr
Copy link
Contributor

Hi Ian,

Nothing concrete. We are exploring different solutions for compliance and there's lots of internal discussion. An update of the plugin may be required to be compliant. We should have further clarity about this closer to the GDPR deadline.

@michaelbourne
Copy link

Wouldn't the plugin legally need opt-in functionality, where the pixel tracking code isn't enqueued on the front end of the site unless the visitor has given explicit permission to do so?

Maybe a better solution would be a simple filter that allowed us to conditionally enqueue the tracking code ourselves, based on our own opt-in implementation. There's little need for multiple plugins having their own notifications, when you can wrap it up into one on your own site and handle your tracking pixels via custom code.

@addedlovely
Copy link
Contributor

Rummaging through the source, found this filter 'facebook_for_woocommerce_integration_pixel_enabled':

add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_false');

@scrobbleme
Copy link

Same here, we just need the sync as the pixel needs user opt-in.

@dmitridr
Copy link
Contributor

dmitridr commented May 18, 2018

Hi All,

Regarding legal concerns, see the image I posted earlier of the pixel step, which links to this page. I think our GDPR policy, www.facebook.com/business/GDPR, has also been updated.

As @addedlovely said, that filter can be used to build your own opt-in solutions, but we will not be taking action on this to implement opt-in behavior. However, we welcome your pull requests if you need additional filters/features to facilitate building those solutions.

I would also look into using PixelYourSite which is compatible with our plugin, they may have an opt-in solution, and they do use the above filter.

@scrobbleme
Copy link

@dmitridr Do I understand your last post right?

  • Disabling the pixel won't be implemented into the plugin?
  • Users should implement their own solutions?

Obviously this is not a good "solution", as this makes it quite hard for users to use this plugin. Not everyone is a developer and can implement a custom solution. It is also not good to "force" opt-in plugin developers to specifically target this plugin.

  • At least their should be a simple "generic" solution, which allows enabled/disabling the pixel with "generic" opt-in plugins. Most plugins offer the ability to enable some Javascript, when consent is given. So some way to disable the pixel with Javascript would be nice.

As you can imagin the opt-in rate will be about 0%. So for most users a checkbox to just disable the pixel would be the most easiest way.

@LuciStan
Copy link

Hi,

For the avoidance of doubt, is Facebook operating as a data controller or a data processor with regards to the Pixel application?

Thanks,
Luci

@dmitridr
Copy link
Contributor

@scrobbleme

Yes I think your understanding is mostly correct:
(1) It's already possible using the filter mentioned above, but regarding a UI, yes we won't build it.
(2) Yes.

The filter given above does allow enabling/disabling the pixel, the line pasted by @addedlovely can be used to disable the pixel with the WP plugin editor. But as you say disabling won't work through JS, we're happy to review your pull request to add that functionality. If you send us a pull request for a checkbox to disable the pixel... we would be happy to consider that as well.

@LuciStan My opinion as a dev : FB is mostly a data controller, I imagine this applies to the pixel as well. I would encourage you to read FB's official stance and draw your own conclusions though, there may be something I'm missing.

@sanderkie
Copy link

Is there a way we can add the suggested line to the Child-Theme?
Am I correct that you would need to create folders similar to the plugin folder which is similar to the Facebook plugin. And then add .... . php file with the mentioned code?

add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_false');

(for security reasons I have WP editor disabled but can access via secure FTP)

@scrobbleme
Copy link

scrobbleme commented May 23, 2018

@sanderkie You can just add it to your functions.php. Maybe set the priority a little higher:

add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_false', 20);

@bweston92
Copy link

So do we need to ask for consent to use the pixel or not?
The documents in the links provided aren't simple enough.

@dmitridr said:
"Specific to the FB pixel, Facebook is pursuing a solution at the user level that will require very little action for businesses who installed the pixel. There will be no need to remove the pixel, and the requirements to provide notice to users will be largely the same as they are now."

Is this still the case?

@fabiograsso
Copy link

fabiograsso commented May 5, 2020

I came back against the integration with Iubenda Cookie Solution. There was some changes in facebook-for-woocommerce code, so my solution is not working anymore.

I have investigated and I think it can be resolved in an alternative way: Iubenda allows you to block Javascript code in two ways:

  1. by inserting <!-- IUB-COOKIE-BLOCK-START --> <!-- IUB-COOKIE-BLOCK-END --> in the code

  2. by modifying the scripts code:
    <script class="_iub_cs_activate" type="text/plain" src="code-source.js">
    or

<script type="text/plain" class="_iub_cs_activate-inline">
...
</script>

The first solution is difficult to apply on this plugin, because there is nothing that allows you to insert arbitrary code before and after the pixel script. So this could be a feature request: add a parameter for the HTML code to be inserted before and after that of the pixel.

Solution 2:
I thought I'd override the wc_facebook_pixel_script_attributes filter with this code:

add_filter ( 'wc_facebook_pixel_script_attributes',' wc_facebook_pixel_script_at
tributes_callback ');
function wc_facebook_pixel_script_attributes_callback () {
  return array ('type' => 'text / plain', 'class' => '_iub_cs_activate-inline');
}

Here, however, a problem arises: the event code (e.g. fbq ('track', 'PageView')) is executed before the Facebook Javascript is loaded, therefore the event is not sent because the function fbq() does not is still defined.

Iubenda allows you to define a prerequisite for scripts like this:
<script type = "text / plain" class = "_ iub_cs_activate-inline" data-iub-cs-wait-for = fbq "> so my function could become:

function wc_facebook_pixel_script_attributes_callback () {
  return array ('type' => 'text / plain', 'class' => '_iub_cs_activate-inline', 'data-iub-cs-wait-for' => 'fbq');
}

Here, however, another problem arises: the same code is applied both to the part of the script that loads the Pixel from Facebook and to that of the actions, so in this case no script is loaded because the part of the script that loads https://connect. facebook.net/en_US/fbevents.js waits for fbq to be available, but this will never be available until that piece of code is loaded ... in short, an infinite loop.

Here comes the second feature request: distinguish the filter wc_facebook_pixel_script_attributes so that it's different in the case of loading the main script and events.
For example by creating a second filter named wc_facebook_pixel_script_attributes_events.

This would allow you to correctly handle the script with Iubenda with something like:

add_filter('wc_facebook_pixel_script_attributes','wc_facebook_pixel_script_attributes_callback');
function wc_facebook_pixel_script_attributes_callback() {
  return array( 'type' => 'text/plain', 'class' => '_iub_cs_activate-inline' );
}

add_filter('wc_facebook_pixel_script_attributes_events','wc_facebook_pixel_script_attributes_events_callback');
function wc_facebook_pixel_script_attributes_events_callback() {
  return array( 'type' => 'text/plain', 'class' => '_iub_cs_activate-inline', 'data-iub-cs-wait-for' => 'fbq' );
}

This example is for Iubenda, but a lot of other cookie blocking solution uses the same logic, so I think it will be applicable to other cookie management scripts.

What do you think?

@fabiograsso
Copy link

Hello all,
I've further investigate, I think that there is no need to differentiate the filter as reported in my previous comment. Change of wc_facebook_pixel_script_attributes is enaugh and for my test there is no need to wait for fbq() to be ready, as scripts are executed sequentially.

Follow some example of code for various cookie block solutions:

Example for Iubenda:

add_filter('wc_facebook_pixel_script_attributes','wc_facebook_pixel_script_attributes_callback');
function wc_facebook_pixel_script_attributes_callback() {
  return array('type' => 'text/plain', 
               'class' => '_iub_cs_activate-inline', 
			   'data-iub-purposes' => 5);
}

Example for Cookie Bot:

add_filter('wc_facebook_pixel_script_attributes','wc_facebook_pixel_script_attributes_callback');
function wc_facebook_pixel_script_attributes_callback() {
  return array('type' => 'text/plain', 
               'data-cookieconsent' => 'marketing');
}

Example for Cookie Script:

add_filter('wc_facebook_pixel_script_attributes','wc_facebook_pixel_script_attributes_callback');
function wc_facebook_pixel_script_attributes_callback() {
  return array('type' => 'text/plain', 
               'data-cookiecategory' => 'targeting',
			   'data-cookiescript' => 'accepted');
}

Now we have anothe problem: some events are enqueued in Woocomerce js and so cannot be change using this method (as reported in #1268). In order to make this work for all events we need to change inject_event function in facebook-commerce-pixel-event.php in order to print the full HTML code (see my pull request )

I've made also a pull request with this changes: #1274

@emporio3
Copy link

Hi Fabio,
at first thanks for your precious help.
We are not developers so we have some questions:

1- is the problem solved or as we read something still doesn't work?
2- we still have to keep the old modify in facebook-commerce-pixel-event.php
3- which is the last modify to use and where we have to put it?

Thanks so much

@fabiograsso
Copy link

fabiograsso commented May 11, 2020

Ciao @emporio3

1- is the problem solved or as we read something still doesn't work?

Problem is not solved, but I've found out a possible workaround

2- we still have to keep the old modify in facebook-commerce-pixel-event.php

Which version of the plugin are you using? If you are using a version released before July 2019 (I think it was 1.9.x), the old modify is working.

3- which is the last modify to use and where we have to put it?

For the actual version I've made this changes:

  1. Add this code to your theme's function.php:
add_filter('wc_facebook_pixel_script_attributes','wc_facebook_pixel_script_attributes_callback');
function wc_facebook_pixel_script_attributes_callback() {
  return array('type' => 'text/plain', 
               'class' => '_iub_cs_activate-inline', 
			   'data-iub-purposes' => 5);
}

(this example is for Iubenda, change it according to your cookie blocking solution)

  1. Then you have to modify facebook-commerce-pixel-event.php on line 280, change:
		public function inject_event( $event_name, $params, $method = 'track' ) {

			if ( \WC_Facebookcommerce_Utils::isWoocommerceIntegration() ) {

				\WC_Facebookcommerce_Utils::wc_enqueue_js( $this->get_event_code( $event_name, self::build_params( $params, $event_name ), $method ) );

			} else {

				// phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				printf( $this->get_event_script( $event_name, self::build_params( $params, $event_name ), $method ) );
			}
		}

in

		public function inject_event( $event_name, $params, $method = 'track' ) {

				// phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped
				printf( $this->get_event_script( $event_name, self::build_params( $params, $event_name ), $method ) );
 
		}

In short I've removed the if...then...else statement in order to avoid sending the Javascript code of the Pixel for events via the Woocommerce code queuing system (wc_enqueue_js). Doing this I force the printf, so that it writes all the Javascript code, including <script type = ....>

I tested this workaround with the Iubenda plugin and it works correctly, I submitted a pull request to include this change in the facebook-commerce-pixel-event.php file but until it will be implemented (or if it will be rejected) it must be changed by hand.

I hope I was helpful

@emporio3
Copy link

Thanks so much as usual

@brrrm
Copy link

brrrm commented Sep 1, 2020

Hi, Am I correct to notice that this filter is no longer blocking the pixel?

add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_false', 20);

In de log-file I can still see the queries and responses to and from FB.

@beanslel
Copy link

Hi, Am I correct to notice that this filter is no longer blocking the pixel?

add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_false', 20);

In de log-file I can still see the queries and responses to and from FB.

It's still working for me. The queries you're seeing in the log may be the backend FB integration (product sync etc).

For anyone using the GDPR Cookie Consent (CCPA Ready) plugin, the following will act as an opt-in and only enable the pixel if non-essential cookie consent is given.

add_action( 'init', 'maybe_consent_woocommerce');
function maybe_consent_woocommerce() {
    // Only display the tracking code if the user has accepted the GDPR Cookie Consent policy
    if ($_COOKIE['viewed_cookie_policy']=='yes' && $_COOKIE["cookielawinfo-checkbox-non-necessary"] =='yes') {
		add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_true');
    }else{
		add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_false');
	}
}

@simonporter007
Copy link

Hi @brrrm

Hi, Am I correct to notice that this filter is no longer blocking the pixel?

add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_false', 20);

In de log-file I can still see the queries and responses to and from FB.

@beanslel is correct! In v2.0+ we can now use the server to server pixel tracking API. This will record events in your debug log but wouldn't be loading a pixel on the front end if you have still disabled that like previously.

Cheers,

@emporio3
Copy link

emporio3 commented Oct 29, 2020

Hi,
i had install the last version 2.1.2 and it still doesn't work anymore for me.
This is the screenshot of the coockies..Could you help me pls?
facebook

@haszari haszari added type: enhancement The issue is a request for an enhancement. and removed feature-request labels Mar 22, 2021
@diegosomar
Copy link

add_action( 'init', 'maybe_consent_woocommerce');
function maybe_consent_woocommerce() {
    // Only display the tracking code if the user has accepted the GDPR Cookie Consent policy
    if ($_COOKIE['viewed_cookie_policy']=='yes' && $_COOKIE["cookielawinfo-checkbox-non-necessary"] =='yes') {
		add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_true');
    }else{
		add_filter('facebook_for_woocommerce_integration_pixel_enabled', '__return_false');
	}
}

@beanslel Tks, your solution works.
The GDPR Cookie Consent (CCPA Ready) plugin is now called CookieYes.

@edirpedro
Copy link

I'm getting problems when combining this with cached pages, using Varnish for example. this is my scenario:

  1. Can't create a custom cache on the server, I need to use the host solution only.
  2. Can't use the PHP filter "facebook_for_woocommerce_integration_pixel_enabled" because the page will be cached without the Pixel and served to all other users.
  3. I can only rely on the client side to handle the opt-in and out for Pixel, but I didn't find a way to manage this.

What I think that could be a solution, just an ideia, not tested.

Instead of add the scripts direct on the page, we need a JS Hook to check if this can be done or not and only after that we add the script source and all the rest to start up the Pixel or any other third party application. Like this using WP JS Hooks:

addFilter( 'facebook_for_woocommerce_integration_pixel_enabled', 'facebook_for_woocommerce', consent_for_facebook_pixel );
function consent_for_facebook_pixel() {
    return document.cookie.indexOf('consent-facebook-pixel=true') >= 0;
}

Without checking the user consent on the server side, there is no problem creating caches on the server or using a CDN, the Pixel will be on the HTML but only injected on the page after checking it on the client side, according to user consent.

@budzanowski
Copy link
Collaborator

It looks like this issue can be closed given the results of the discussion.

@edirpedro if you still are encountering problem with the implementation please create a separate issue that will be focused on the pixel in the context of cached sites.

@mircobabini
Copy link

@edirpedro @fabiograsso

#301 (comment) this is still an issue. Huge one. Did you find a way to work around this?

@mircobabini
Copy link

Sharing my idea here.

  1. remove_action( 'wp_head', array( facebook_for_woocommerce()->get_integration()->events_tracker, 'inject_base_pixel' ) ); so the fbq() javascript + the PageView code is never injected
  2. Integrate GTM + Iubenda passing the iubenda_consent_given_purpose_X params
  3. Inject the library + the PageView via GTM

Don't know if there's other javascript injected from this plugin into the page body (then executing before GTM). That won't work.

@edirpedro
Copy link

@mircobabini No solution here, if you use a cache service like Varnish or a CDN, you will not conform to GPDR ever. The option to disable this injection is restricted to the server side!

@mircobabini
Copy link

@edirpedro so, the only GDPR compliant way is to rely on GTM (injected scripts based on consent conditions) completely. Nothing generated by the server and put into the page body (cached).

@edirpedro
Copy link

@mircobabini yes, Meta wants to track the user even when it revokes the Pixel, that's the poor solution they provide at the documentation fbq('consent', 'revoke');.

@mircobabini
Copy link

@edirpedro yeah. So the idea is to never block the Pixel library to load, but adding the fbq('consent', 'revoke'); just before every other fbq() call to ensure nothing will be sent to facebook, until a grant is given. Still not compatible with with full page cache systems though 🤷‍♂️

@edirpedro
Copy link

@mircobabini a workaround could be using the plugin to serve the Data Feed only, just disabling it add_filter( 'facebook_for_woocommerce_integration_pixel_enabled', '__return_false' ) then add the Pixel script manually, building your own solution to handle the user consent on the client side.

@mircobabini
Copy link

@edirpedro disabling that integration makes that plugin almost useless though (if you are relying on their pixel integration which is pretty complex to replicate).

I came up with a partially working solution (for Iubenda).
It's based on your idea: always revoke immediately and grant (javascript) based on the user consent, later on (but still early).

  1. Inline load the fbq function and revoke pretty early (before iubenda, before the lib loading from Facebook for WooCommerce):
<?php
/**
 * Priority lower than Iubenda inline enqueue
 */
add_action( 'wp_enqueue_scripts', function(){
	wp_register_script( "fbq-pixel-earlier", ' ' );// phpcs:ignore WordPress.WP.EnqueuedResourceParameters.NotInFooter,WordPress.WP.EnqueuedResourceParameters.MissingVersion
	wp_enqueue_script( "fbq-pixel-earlier" );
	wp_add_inline_script(
		"fbq-pixel-earlier",
		"!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
				n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
				n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
				t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
				document,'script','https://connect.facebook.net/en_US/fbevents.js');

				window.fbq && window.fbq('consent', 'revoke');",
		'after'
	);
}, 9 );
  1. Then, take the Iubenda snippet https://www.iubenda.com/en/help/1235-google-tag-manager-blocking-cookies#installIUB
  2. Slightly change the callback function adding this:
} else if (preference.purposes) {
    if (preference.purposes[4] === true) {
        window.fbq && window.fbq('consent', 'grant');
    }

RESULTS

When consent is not given:
Screenshot 2023-07-06 at 18 39 29

When given (at least "Measurement"):
Screenshot 2023-07-06 at 18 42 14

Hacky but working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GDPR type: enhancement The issue is a request for an enhancement.
Projects
None yet
Development

No branches or pull requests