Adsense revenue sharing does not work when page caching is on

kbahey - February 12, 2008 - 14:05
Project:AdSense
Version:5.x-3.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:needs work
Description

This has been reported by a few people, such as Frank.dev here:

If I activate the caching mode for the Drupal-site (Administer >> Site configuration >> Performance: Caching mode: "Normal"), it is indicated again generally the Adsense client ID of a user - revenue_sharing does not work.

All the same which setting I choose - "Percentage of node views going to author: 5 - 90" - it is always the same result. Either is indicated generally the Adsense client Id of the Site owner or the author.

If I disabled the cache, the indicated ID's alternate in the source correctly.

This is a known limitation. Page caching caches all the end result of HTML's page and serves it to the subsequent visitors. So, whatever the Adsense ID happens to be when the page got cached, this will be served to the visitors until the cache expires (duration expires, or new content/comment gets posted).

For now, the workaround is to disable caching, which is OK for sites that do not have a lot of taffic.

#1

Petra - February 12, 2008 - 19:57

Evident.
You wrote:

So, whatever the Adsense ID happens to be when the page got cached, this will be served to the visitors until the cache expires (duration expires, or new content/comment gets posted).

What empties cache when I set a cache duration - and no content/comment is posted or edited?
Will drupal check cache time before he delivers the site? Or does cron check this and empties the cache when duration is expired?
(I thougt cache duration is only for high traffic sites. P.e. when every minute a comment is posted, I set a cache duration for 10 minutes. So cache will be emptied only every 10 minutes. But when I have a site where nothing changes over 3 days, cache will not be emptied before I edit or post some content/comment).

Will this be the same in drupal 6?

#2

kbahey - February 13, 2008 - 02:11

Petra

The cache is expired either when new content/comment is posted (as well as other things, such as enabling modules, changing the menu, ...etc.), OR when the period expires.

If you set the cache to expire every 15 minutes, then even if you post a comment, the cache will not expire until 15 minutes has passed.

In any case, I committed a workaround for 5.x-2.x that displays a message in adsense settings if cache is enabled, and revenue sharing is enabled. It does not fix the problem, but at least tells the admin that things may not work.

A similar problem exists for using tags inside content with caching.

With the current design of Drupal, I don't think there will be a solution to this issue in adsense itself. It has to be at Drupal's level.

#3

Petra - February 14, 2008 - 15:21

When drupal 6 will have the same cache mechanism, a solution would be fine.

My idea is to set cache duration to one hour - so every hour the dice rolls for the Adsense-Client-Id.
So I can enable cache and be sure that revenue is shared.

But what happens, if nothing is changed on a site for several days. Will cache be emptied or not?

I think cache mechanism works like I described here: http://drupal.org/node/142242#comment-235668

If I'm right and if nothing is changed on a site, there is no way for the Drupal core to know that cache has expired, and old content will be held in the cache.

So to be sure that cache is emptied after an hour, I have to write a module that uses hook_cron to call cache_clear_all(), described here: http://drupal.org/node/103995#comment-181373
and I have to run cron every hour. Right?

#4

kbahey - February 13, 2008 - 22:10

Regardless of how the cache works, we can enforce a cache flush.

We don't even need cron for this. We can do it in hook_init() in revenue_sharing_basic.module or even adsense.module.

We store when did we last flush the cache, and say how often we should flush, then when a page view comes in we check that and flush if X minutes have passed, regardless of how often cron runs.

This can be in adsense.module advanced settings.

What do you think?

#5

Petra - February 14, 2008 - 14:20

I think it's a valid method for revenue sharing to throw the dice for the Adsense ID every X minutes. So it can go into the module.
And I think it's a good solution to the cache problem. It also could be an example to solve the similar problem using tags inside content with caching.

It should go into revenue_sharing_basic.module, cause it's only needed for revenue sharing:

--Revenue sharing options--

X Enable revenue sharing
Note that enabling this will disable AdSense code caching, which
~ Note that revenue sharing is not working reliably when cache is enabled. Disabling cache can cause more resource usage for busy sites. The referral feature requires the referral module to be installed.
(or did you really disable caching?)

Enforce cache flush
0-X minutes
~ If cache is enabled, you can flush the cache to throw the dice for the Adsense ID...
+ a hint what happens, if cache duration is enabled

Percentage of node views going to author:
50

#6

kbahey - February 20, 2008 - 14:42

I revised this part, and it seems OK:

[ ] Enable revenue sharing
~ Note that revenue sharing does not work reliably when cache is enabled. Disabling cache guarantees that each
page view gets a chance of revenue sharing, but can cause more resource usage for busy sites. Alternatively you
can force cache flush every certain number of minutes. See the option below for this.

The referral feature requires the referral module to be installed.

This part needs better rewording. Can someone please suggest better English wording?

Enforce cache flush
0-X minutes
~ If cache is enabled, you can flush the cache to throw the dice for the Adsense ID...
+ a hint what happens, if cache duration is enabled

#7

funana - February 27, 2008 - 19:22

+1

A solution for this is needed!

*subscribing

#8

kbahey - March 2, 2008 - 00:38

Anyone wants to contribute a patch?

The patch should do what I described in #4: we have a function revenue_sharing_init() and we check the last time the refresh was done, and check the option (below) and refresh the cache every X minutes:

<?php
function revenue_sharing_basic_init() {
 
$last_refresh = variable_get(REVENUE_SHARING_LAST_REFRESH, 0);
 
$interval = variable_get(REVENUE_SHARING_REFRESH_INTERVAL, 0);

  if (
$interval) {
     if (
time() > ($last_refresh + $interval)) {
      
cache_clear_all('adsense', 'cache', TRUE);
      
variable_set(REVENUE_SHARING_LAST_REFRESH, time());
     }
   }
}
?>

The settings would have a new option like so:

Enforce periodic refresh of revenue sharing
Drop down list
None (0)
1 minutes
2
3
5
10
15
30
1 hour
3 hours
6 hours

If Adsense caching is enabled, and you have revenue sharing as well, you may want to cause a periodic "roll of the dice" for page views. By doing so, the adsense cache will be flushed every X minutes, and a chance of changing the Google Adsense ID per the revenue sharing settings.

And we need REVENUE_SHARING_REFRESH_INTERVAL to be set above in the settings.

Please revise the wording.

Can anyone submit a patch for this?

#9

Petra - March 2, 2008 - 14:48

Here is a patch. But it does not work: revenue_sharing_basic_init() is not called for anonymous users - only when I'm logged in.
I don't know how to fix this.
(I added 45 minutes cause min-cache-duration also has this option.)

AttachmentSize
revenue_sharing_basic-refresh.patch 2.4 KB

#10

kbahey - March 3, 2008 - 02:45

Petra, are you using aggressive caching or normal caching?

#11

Petra - March 3, 2008 - 10:53

kbahey, I use normal caching.

And I see the notice: "The following enabled modules are incompatible with aggressive mode caching and might not function properly: path_redirect, revenue_sharing_basic, token."

#12

Summit - March 4, 2008 - 12:38

Subscribing, I will test adsense 2.dev with revenue sharing, greetings, Martijn

#13

Petra - April 14, 2008 - 17:16

Can I do something to solve this issue? Please, let me know.

#14

drupalina - May 21, 2008 - 03:57

subscribing

(a small comment: GoogleAds generates income only on relatively high-traffic sites And the speed of pageloads in essential. So it makes sense to have a caching compatibility for Revenue Sharing. I tried Revenue Sharing, but had to disable it _only_ because disabling my Normal caching made my pageloads slower and very user-unfriendly)

#15

jcnventura - December 18, 2008 - 08:56
Version:5.x-2.x-dev» 5.x-3.x-dev
Status:active» won't fix

This seems to be impossible to handle.. If Drupal's cache is enabled, then it will store an 'image' of the page when it last served it, and it will keep re-using that page from cache until it expires or the page is modified.

The only way to make this work would be to invalidate the cache all the time. Which would make it useless to have cache enabled in the first place.

This can be reactived later on if someone finds a way to modify a page after it is retrieved from the cache, but before being sent to the user's browser.

#16

mpaler - September 6, 2009 - 16:41

Will using ajax solve this problem?

#17

mpaler - September 26, 2009 - 19:01
Status:won't fix» needs review

Hi,

I believe I've solved this problem for cached pages by using ajax. I've tested and it works on normally cached pages. Attached is a patch for review.

In a nutshell here's how it works:

1. If user is anonymous, in the adsense_display function (adsense.module) we run a different function:

if ($user->uid) {
  // User is logged in.
  $ad = _adsense_oldcode_get_ad($args['format'], $client, $args['group'], $args['channel']);
} else {
  $ad = _adsense_oldcode_get_ad_anon($args['format'], $client, $args['group'], $args['channel']);
}

2. In the new function, _adsense_oldcode_get_ad_anon, we insert some js inline into the header that will create an ajax call back to revenue_sharing_basic.module to fetch the publisher id and set it as a global js variable.

// First add the ajax function to the header as inline js.
// Note we need to tack the node id to the end of the
// callback (ajaxURL) so we can track down the author
// when the function is called. This works for both regular nodes
// and panel pages. If no argument is present, the function
// will return the default publisher id.
if ( arg(0) == 'node' && is_numeric(arg(1))) {
$path = 'pub_id_anon/' . arg(1);
} else {
$path = 'pub_id_anon';
}
drupal_add_js('
var ajaxURL="' . url($path, null, null, true) . '";
var pub_id;
function loadPubID() {
pub_id = $.ajax({
      url: ajaxURL,
      async: false
  }).responseText;
}
loadPubID();
',
'inline',
'header');

In this same function, when we embed the google embed code, we reference the global js variable as follows:

google_ad_client = "pub_id";

3. Created a new menu callback in revenue_sharing_basic.module (called by the ajax above). This in turn calls a slightly modified revenue_sharing_basic_choose_client function that now accepts node_id as an optional argument and returns a json formatted publisher id.

function revenue_sharing_anon_pub_id($node_id = NULL){

// Retrieve the publisher id. If $node_id is empty,
// returns default publisher id
$reply = revenue_sharing_basic_choose_client($args,$node_id);
print drupal_to_js($reply);
exit();
}

I've also added an administration testing setting that let's you see the publisher_id that get's returned.

Some important points.

1. Patch is rolled against the 5.x-3.x-dev 2009-Sep-02 release
2. This whole routine only works if you are logged out.
3. This setup requires that all of your js be loaded in the head of your page. Otherwise the google ad embed will load first and reference an undefined variable.

Feedback is welcome though my time is very limited at the moment.

AttachmentSize
rev_share_cache_1.patch 11.8 KB

#18

jcnventura - October 2, 2009 - 22:30
Status:needs review» needs work

Hi,

The 'adsense_anonymous_test_mode' setting is completely unnecessary, the existing 'adsense_test_mode' is completely adequate for this also.

Why does the new function duplicate all the existing ad generating code from the managed ads module? Why aren't you re-using that code?

Finally, there's too much duplication inside revenue_sharing_basic_get_node_info().. I think that modifying this function to always accept the $nid parameter would improve the code a bit.

João

#19

CarbonPig - October 4, 2009 - 17:29

subscribe

 
 

Drupal is a registered trademark of Dries Buytaert.