Hi!

Based on https://www.drupal.org/node/2592307#comment-10454049, it is clear that once a page is served from cache we cannot invoke any hook or functions. However, I might need to serve a javascript snippet(different per user) which lives on the < header > of cached pages. Would you mind pointing me on the right direction? or, is this even possible?

AFAIK, the authcache_builtin_cacheinc_retrieve_cache_page function gets the cache object then the authcache_serve_page_from_cache function serves it. I would just modify any of those two functions. Is there any other solution?

-Another approach could be serve the script within the body of the document (maybe a cached block per user), but I need the javascript snippet in the < header >

Comments

angel.angelio created an issue. See original summary.

znerol’s picture

Category: Plan » Support request

Instead of trying to serve different assets (scripts) for different users, I'd recommend to build the scripts in a way such that they can be delivered to any user. Then use some value from Drupal.settings to decide whether or not to run the script. Authcache is capable of populating Drupal.settings selectively via Ajax/ESI. You can provide your own callbacks via hook_authcache_p13n_setting. Take a look at the Authcache User module for a good example. It is responsible for populating the contact form.

You might want to use the following skeleton:

MYMODULE.module

/**
 * Implements hook_authcache_p13n_setting().
 */
function MYMODULE_authcache_p13n_setting() {
  return array(
    'user' => array(
      'admin name' => t('Per user custom setting'),
      'admin group' => t('My module'),
      'admin description' => t('Provide custom per user data'),
      'setting' => array(
        '#setting' => 'mymodule',  // Name of the URL query parameter used when retrieving the setting value.
        '#target' => 'myModule', // Key to use when populating Drupal.settings.
        '#class' => 'MyModuleSetting', // Name of class to use when retrieving the setting value.
      ),
      'cache maxage' => 86400, // Cache-Control max-age
    ),
  );
}

/**
 * Setting handler for custom per user data of currently logged in user.
 */
class MyModuleSetting implements AuthcacheP13nSettingInterface {
  /**
   * Return custom per user data of currently logged in user.
   */
  public function get($params, $context) {
    return array(
      'foo' => 'bar';
    );
  }
}

MYMODULE.js

(function (Drupal, $) {
  "use strict";

  Drupal.behaviors.authcacheUser = {
    attach: function (context, settings) {
      if (settings.myModule) {
        // do something with settings.myModule.foo;
      }
    }
  };

}(Drupal, jQuery));
angel.angelio’s picture

Issue summary: View changes
angel.angelio’s picture

Issue summary: View changes
angel.angelio’s picture

Thanks for replying. Really appreciate it.

Assuming that I can build the script in such way that I can delivery it to any user then it does make sense to use the hook_authcache_p13n_setting. However, I think I cannot invoke any hook when a page is being serve from cache (which I think is what I need in order to embebed a customize javascript snippet per user in the < header >). Or, am I overthinking this? I think the problem is that I cannot modify the HTML from the < header > once the page it is being serve from cache.

znerol’s picture

There is no session at the time when a cached page is sent to the user. So even customizing authcache_serve_page_from_cache() does not buy you much because it is impossible to tell users apart yet.

What is the use case you are trying to solve? What does require a user specific inline script in the head element?

angel.angelio’s picture

What if I bootstrap the session before authcache_builtin_cacheinc_retrieve_cache_page ? then modify the cached page on authcache_serve_page_from_cache? maybe not the best idea.

The use case is Google Analytics custom dimensions, the GA tracking code should/has to be place on the < head >

Paste your snippet (unaltered, in its entirety) into every web page you want to track. Paste it immediately before the closing < / head > tag.

I am sending custom dimensions to GA based on users's data / roles and IMO the best way to do it is placing them into the < head >

znerol’s picture

Do you want to use User ID tracking (or any per-user dimension) or are you only interested in roles?

znerol’s picture

As a general rule I'd recommend to just set a cookie in the client during login/logout and store any ga-settings there. In order to do that just implement hook_authcache_cookie():

/**
 * Implements hook_authcache_cookie().
 */
function MYMODULE_authcache_cookie($account) {
  if ($account->uid) {
   
    $cookies['ga_uid'] = array(
      'present' => TRUE,
      'value' => $account->uid;
    );
  }
  else {
    $cookies['ga_uid']['present'] = FALSE;
  }

  return $cookies;
}

Then in your ga javascript snipped to something like this (reference):

<!-- Google Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', 'UA-XXXXX-Y', 'auto');

/* BEGIN: customization */
var userid = $.cookie("ga_uid");
if (userid) {
  ga('set', 'userId', userid);
}
/* END: customization */

ga('send', 'pageview');
</script>
<!-- End Google Analytics -->


angel.angelio’s picture

Yes I am interested on roles and some user's data.

Understood, that makes a lot of sense. I will give it a try.

znerol’s picture

Status: Active » Fixed

I guess the original question is answered. Please open a new issue if there is still something unclear.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.