In the process of developing anti-spam plugin CleanTalk for WordPress we faced with the problem of caching of dynamic JavaScript code on the frontend of sites. Namely, if you place JavaScript that contains any pieces of code that can be dynamically inserted from backend site, in the presence on the site of any plug-in caching pages, JavaScript code is not possible to use as directed.

Consider the example

In the backend we have the template of JavaScript code,

 <?php
$html = '
<script type="text/javascript">
function ctSetCookie(c_name, value, def_value) {
 document.cookie = c_name + "=" + escape(value.replace(/^def_value$/, value)) + "; path=/";
}
ctSetCookie("%s", "%s", "%s");
</script>
'; 

$ct_checkjs_key = rand(0,100); // The value of the variable dynamic
$field_name = 'ct_checkjs'; // The value of a static
$ct_checkjs_def = 0; // The value of a static

$html = sprintf($html, $field_name, $ct_checkjs_key, $ct_checkjs_def);
?>

An example of the output on the frontend,

 <script type="text/javascript">
function ctSetCookie(c_name, value, def_value) {
document.cookie = c_name + "=" + escape(value.replace(/^def_value$/, value)) + "; path=/";
}
ctSetCookie("ct_checkjs", "455", "0");
</script>

Accordingly, the cache gets the JavaScript code in which parameter value of function ctSetCookie unchanged on all pages of the site and the same for all visitors, which leads to the impossibility of using JavaScript individually for each visitor. Consider options for solutions.

Use built-in tools to disable caching

If the plug-in of caching of content on WordPress more or less popular, then it is bound to have a means to exclude a list of pages from the cache. For example, for the WP Super cache, you can specify in your plug-in code line,

define( "DONOTCACHEPAGE", true );

This will be enough for your pages with dynamic code were not included in the cache. The disadvantages of this approach,

It is necessary to integrate and test your plug-in with popular caching plug-ins.

Still there will be cases when your code incorrectly works off due to the fact that one or another site is set rarely used plug-in of caching.

And most importantly, this approach virtually eliminates the use of caching plugins, if your JavaScript code is placed on all pages of the website, or on the most loaded pages.

Let’s look at other option solutions.

AJAX call to the backend

The essence of this approach is that on the frontend place only a static JavaScript code, and all that is required to use dynamically obtain the backend of the site through an AJAX call. The example code on frontend,


//
// Making a call to admin-ajax.php
//
function sendRequest(url,callback,postData) {
    var req = createXMLHTTPObject();
    if (!req) return;
    var method = "GET";
    req.open(method,url,true);
    if (postData)
            req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
        req.onreadystatechange = function () {
            if (req.readyState != 4) return;
            if (req.status != 200 && req.status != 304) {
                return;
            }
        callback(req);
    };
    if (req.readyState == 4) return;
    req.send(postData);
    return null;
}
var XMLHttpFactories = [
    function () {return new XMLHttpRequest()},
    function () {return new ActiveXObject("Msxml2.XMLHTTP")},
    function () {return new ActiveXObject("Msxml3.XMLHTTP")},
    function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];
function createXMLHTTPObject() {
    var xmlhttp = false;
    for (var i=0;i<XMLHttpFactories.length;i++) {
        try {
            xmlhttp = XMLHttpFactories[i]();
        }
        catch (e) {
            continue;
        }
        break;
    }
    return xmlhttp;
}

//
// Process the results of the AJAX call.
//
function ct_callback(req)
{
ct_cookie=req.responseText.trim();  
    ct_setCookie('ct_checkjs', ct_cookie);

return null;
}
//
// Set cookie
//
function ct_setCookie(name, value)
{
    document.cookie = name+" =; expires=Thu, 01 Jan 1970 00:00:01 GMT; path = /";
    document.cookie = name+" =; expires=Thu, 01 Jan 1970 00:00:01 GMT";

    var date = new Date;
    date.setDate(date.getDate() + 1);
    setTimeout(function() { document.cookie = name+"=" + value + "; expires=" + date.toUTCString() + "; path = /;"}, 500);

    return null;
}

var ct_ajaxurl = 'http://wordpress.local/wp-admin/admin-ajax.php';
sendRequest(ct_ajaxurl+'?'+Math.random(),ct_callback,'action=ct_get_cookie');

Please pay attention to the structure

ct_ajaxurl+'?'+Math.random()

This approach is used to avoid caching including an AJAX call.

Move to the last listing, look at the backend,


add_action( 'wp_ajax_nopriv_ct_get_cookie', 'ct_get_cookie',1 );
/**
 * Returns a new cookie
*/
function ct_get_cookie()
{
    global $ct_checkjs_def;
    $ct_checkjs_key = ct_get_checkjs_value(true); 
    print $ct_checkjs_key;
    die();
}

Disadvantage of this approach only in one thing – your plug-in does one call more in the backend of WordPress. Given the fact that the hosting service cannot be the fastest or the WordPress can be set more than a dozen plug-ins, such a call would increase the response time of the site.

Good luck in developing for WordPress!

Learn more about CleanTalk Anti-Spam.

Solve the problem with caching of dynamic JavaScript code on the frontend of WordPress
Tagged on:     

Leave a Reply

Your email address will not be published. Required fields are marked *