{"id":421,"date":"2024-02-02T04:49:14","date_gmt":"2024-02-02T04:49:14","guid":{"rendered":"http:\/\/localhost:10008\/?p=421"},"modified":"2024-02-02T12:22:26","modified_gmt":"2024-02-02T12:22:26","slug":"mitigating-performance-impact-from-personalisation","status":"publish","type":"post","link":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/","title":{"rendered":"Mitigating Performance Impact from Personalisation"},"content":{"rendered":"\n
\n

There are only two hard things in Computer Science: cache invalidation and naming things.<\/p>\nPhil Karlton<\/a><\/cite><\/blockquote>\n\n\n\n

\n
\n

This is the 4th post in a series I started while consulting at rtCamp back in 2022. The series of posts<\/a> explored personalisation of page content in order to optimise the conversion rate of lead-generation on a business website<\/em><\/p>\n<\/div>\n<\/div>\n\n\n\n

A multi-brand, multi-site enterprise website may have hundreds of landing pages and possibly thousands of posts and other single content pages.\u00a0 In order to ensure page response time performance is maintained when scaling-up with growing number of visitors, modern CMS frameworks like WordPress leverage page caching technology along with CDNs in order to reduce server-loads and ensure good response performance.\u00a0 However, cached content is pre-rendered static HTML, so how can performance and personalisation coexist?<\/p>\n\n\n\n

Performance impact of personalisation<\/h2>\n\n\n\n

As a general rule of thumb, the following hierarchy of content requests is followed in order to assess the performance impact. At the top, and least impactful on the performance, are requests that are served using cached content.\u00a0 This can be either caching on the client-side in the browser itself, or on the server-side. Cookies play an important role in order to store session states and access credentials and therefore prevent the need to hit the server for such information.\u00a0 At the next level is server rendered requests which requires accessing resources on the server such as the database.\u00a0 Such requests are less performant than those served from cached content. Finally the least performant are requests that require API calls to third party services on external servers.<\/p>\n\n\n\n

\"\"
Rule of thumb for request performance as a function of resource access.<\/figcaption><\/figure>\n\n\n\n

Personalised content based on cookie preferences, such as the preferred theme for reading content on a site (some website offer a dark-mode theme), then the personalisation is already stored in cache and does not require accessing any server resources.<\/p>\n\n\n\n

Personalisation based on first-party data stored on the server will, in most cases, require the content to be rendered on the server and this will impact the performance of the page response time.  In addition, if the conditional data is to be fetched from an external third-party service such as a CDP using an API call, this further impacts the performance and in such cases require additional expensive server resources in order to scale up with increased traffic.<\/p>\n\n\n\n

Caching personalised page variants<\/h2>\n\n\n\n

One way to mitigate the impact on performance is to restrict personalisation variations on landing pages to less than a dozen or so and cache all the variants.\u00a0 This would be feasible if the personalisation is based on segments.\u00a0 A user\u2019s personas\/segments could then be stored\/updated as a cookie and the required request served from the cached page variant for that segment.<\/p>\n\n\n\n

How do cache page variants work?<\/h3>\n\n\n\n

A caching server or sometimes also known as a caching engine<\/em>, is a set of data resources that are stored in RAM memory in order to speed up access to this data and lower the cost of accessing these resources at scale.  Supporting the equivalent scaling with traditional server resources such as databases, hard disks and CPU would require considerably more resources at a higher cost without matching the latency periods of RAM access.<\/p>\n\n\n\n

These cached resources are generally transient, meaning that they may be deleted and replaced by more up-to-date versions of the data.  The control of cached data is determined by Cache-Control header<\/a> directives.  <\/p>\n\n\n\n

The HTTP Caching specification introduced the Vary header<\/a> as a mechanism for content negotiation<\/a> when making page requests to a server.\u00a0 The Vary header can take as a value one or more header parameter names, for example,<\/p>\n\n\n\n

Vary: Accept-Encoding<\/code><\/pre>\n\n\n\n

and the Accept-Encoding header request made from a browser that can handle compressed responses might be,<\/p>\n\n\n\n

Accept-Encoding: compress, gzip<\/code><\/pre>\n\n\n\n

and the server may respond with gzip\u2019ed compressed content as opposed to plain uncompressed HTML text.  This is an example of content negotiation for which the Vary header was initially specified for.<\/p>\n\n\n\n

This is now being leveraged to distinguish requests with content variation such as personalised pages.  Let\u2019s look at how the Vary header is handled by various hosting providers in order to handle multiple variations of a personalised page.<\/p>\n\n\n\n

WordPress VIP cache<\/h3>\n\n\n\n

The WordPress VIP hosting network provides an interface API<\/a> for developers to flag page variations which are then stored on the VIP CDN caching network with a Vary header.\u00a0 The interface<\/a> provides a Vary_Cache class,<\/p>\n\n\n\n

use Automattic\\VIP\\Cache\\Vary_Cache;<\/code><\/pre>\n\n\n\n

which provides functionality to register different segments of users.\u00a0 For example, if a business has two types of customers, say dealers (B2B) and retail (B2C), and want to personalise a landing page depending on the segment to which a user belongs to.\u00a0 The first step would be to register a customer group,<\/p>\n\n\n\n

Vary_Cache::register_group( 'customer' );<\/code><\/pre>\n\n\n\n

The API handles these variations with a custom header and a cookie on the client browser which will store the value \u2018b2b\u2019 for dealer clients and \u2018b2c\u2019 for retail clients.  In addition, instruction to the caching engine is handled automatically with a Vary header.<\/p>\n\n\n\n

Once a visitor is identified as a client, the API can be used to set that user\u2019s appropriate segment,<\/p>\n\n\n\n

\/\/user identified as a dealer.\nVary_Cache::set_group_for_user( 'customer', 'b2b' );<\/code><\/pre>\n\n\n\n

Finally, when a previously identified client makes a request to a page, the API exposes the client\u2019s segment for conditional content personalization, which can send a response with the appropriate content variation for that segment,<\/p>\n\n\n\n

if(Vary_Cache::is_user_in_group_segment( 'customer', 'b2b' )){\n  \/\/display content for dealer clients\n}else if(Vary_Cache::is_user_in_group_segment( 'customer', 'b2c' )){\n  \/\/display content for retail clients\n}else{ \n  \/\/display content for other visitors\n}<\/code><\/pre>\n\n\n\n

As the API handles the cache Vary header automatically, the VIP CDN will store the response such that subsequent requests made by users will be served the correct page version from the cache.The segment personalisation is handled with a cookie stored on the client browser, however, for sensitive conditional data that should not be shown to other segment groups, the API has functionality to encrypt<\/a> the identification string.<\/p>\n\n\n\n

WP Engine cache<\/h3>\n\n\n\n

WPEngine<\/a> makes use of the Vary header with its own custom X-WPENGINE-SEGMENT header which gets populated with the wpe-us segment cookie on the client browser.\u00a0 Therefore, when a user is identified as belonging to a specific segment, the cookie is set,<\/p>\n\n\n\n

setcookie('wpe-us', 'customer-b2b'); \/\/customer is a dealer<\/code><\/pre>\n\n\n\n

The cookie value is passed in a request to the server as the X-WPENGINE-SEGMENT header, therefore pages that are personalised can set conditional personalised content<\/p>\n\n\n\n

\/\/flag this page as having multiple versions to the caching engine.\nheader('Vary: X-WPENGINE-SEGMENT'); \n$cookie_value = $_SERVER[\"HTTP_X_WPENGINE_SEGMENT\"];\nif ($cookie_value == 'customer-b2b') {\n    \/\/dealer content\n} else if ($cookie_value == 'customer-b2c') {\n    \/\/retail content\n} else {\n    \/\/default content\n}<\/code><\/pre>\n\n\n\n

Setting the Vary: X-WPENGINE-SEGMENT header at the start of the page will ensure the caching engine stores this page as a variation based on the value of the cookie in the browser, and subsequent requests will be served from the cache.\u00a0 A plugin is available<\/a> to leverage WPEngine segment caching with the help of shortcodes.<\/p>\n\n\n\n

Pantheon cache<\/h3>\n\n\n\n

Pantheon<\/a> hosting service uses a special cookie template to distinguish between different versions of a page.\u00a0 Any pages that setup a cookie named with the prefix STYXKEY<\/a> is flagged by Pantheon\u2019s global CDN caching engine with a Vary header,<\/p>\n\n\n\n

Vary: Cookie<\/code><\/pre>\n\n\n\n

Following our previous example setting a cookie,<\/p>\n\n\n\n

set_cookie('STYXKEY_customer', 'b2b'); <\/code><\/pre>\n\n\n\n

for a personalised page will cache<\/a> the page as content for dealer customers. <\/p>\n\n\n\n

A note of caution<\/h2>\n\n\n\n

Content caching is an important tool in optimising the performance of a website in order to ensure it can scale up with higher traffic and page requests.  However, a page cache is still a limited resource, it is therefore important to limit the amount of cache memory used by reducing the number of pages cached, and hence the number of variations of pages by limiting the number of user segments as well as reducing the number of pages that are personalised.<\/p>\n\n\n\n

Conclusion<\/h2>\n\n\n\n

Personalising page content on WordPress is easy, but requires some precautions in order to make sure these pages scale up.  Caching this personalised content as different versions of the same page is readily feasible  with hosting services such as WordPress VIP, WPEngine and Patheon as well as others but requires planning in order to ensure the cache server is not overloaded with too many page versions.<\/p>\n","protected":false},"excerpt":{"rendered":"

Caching web pages, especially using a Content Development Network is an important step towards a robust and scalable solution. It is possible to cache multiple versions of a page. <\/p>\n","protected":false},"author":1,"featured_media":424,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15],"tags":[24],"yoast_head":"\nMitigating Performance Impact from Personalisation - Tiffin Consulting<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Mitigating Performance Impact from Personalisation - Tiffin Consulting\" \/>\n<meta property=\"og:description\" content=\"Caching web pages, especially using a Content Development Network is an important step towards a robust and scalable solution. It is possible to cache multiple versions of a page.\" \/>\n<meta property=\"og:url\" content=\"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/\" \/>\n<meta property=\"og:site_name\" content=\"Tiffin Consulting\" \/>\n<meta property=\"article:published_time\" content=\"2024-02-02T04:49:14+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-02-02T12:22:26+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/fine-tuning-the-machine.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1599\" \/>\n\t<meta property=\"og:image:height\" content=\"900\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Aurovrata V.\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Aurovrata V.\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\n\t \"@context\": \"https:\/\/schema.org\",\n\t \"@graph\": [\n\t {\n\t \"@type\": \"Article\",\n\t \"@id\": \"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/#article\",\n\t \"isPartOf\": {\n\t \"@id\": \"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/\"\n\t },\n\t \"author\": {\n\t \"name\": \"Aurovrata V.\",\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6\"\n\t },\n\t \"headline\": \"Mitigating Performance Impact from Personalisation\",\n\t \"datePublished\": \"2024-02-02T04:49:14+00:00\",\n\t \"dateModified\": \"2024-02-02T12:22:26+00:00\",\n\t \"mainEntityOfPage\": {\n\t \"@id\": \"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/\"\n\t },\n\t \"wordCount\": 1313,\n\t \"publisher\": {\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6\"\n\t },\n\t \"keywords\": [\n\t \"Lead generation\"\n\t ],\n\t \"articleSection\": [\n\t \"Development\"\n\t ],\n\t \"inLanguage\": \"en-US\"\n\t },\n\t {\n\t \"@type\": \"WebPage\",\n\t \"@id\": \"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/\",\n\t \"url\": \"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/\",\n\t \"name\": \"Mitigating Performance Impact from Personalisation - Tiffin Consulting\",\n\t \"isPartOf\": {\n\t \"@id\": \"http:\/\/localhost:10008\/#website\"\n\t },\n\t \"datePublished\": \"2024-02-02T04:49:14+00:00\",\n\t \"dateModified\": \"2024-02-02T12:22:26+00:00\",\n\t \"breadcrumb\": {\n\t \"@id\": \"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/#breadcrumb\"\n\t },\n\t \"inLanguage\": \"en-US\",\n\t \"potentialAction\": [\n\t {\n\t \"@type\": \"ReadAction\",\n\t \"target\": [\n\t \"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/\"\n\t ]\n\t }\n\t ]\n\t },\n\t {\n\t \"@type\": \"BreadcrumbList\",\n\t \"@id\": \"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/#breadcrumb\",\n\t \"itemListElement\": [\n\t {\n\t \"@type\": \"ListItem\",\n\t \"position\": 1,\n\t \"name\": \"Home\",\n\t \"item\": \"http:\/\/localhost:10008\/\"\n\t },\n\t {\n\t \"@type\": \"ListItem\",\n\t \"position\": 2,\n\t \"name\": \"Mitigating Performance Impact from Personalisation\"\n\t }\n\t ]\n\t },\n\t {\n\t \"@type\": \"WebSite\",\n\t \"@id\": \"http:\/\/localhost:10008\/#website\",\n\t \"url\": \"http:\/\/localhost:10008\/\",\n\t \"name\": \"Tiffin Consulting\",\n\t \"description\": \"digital business transformation\",\n\t \"publisher\": {\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6\"\n\t },\n\t \"potentialAction\": [\n\t {\n\t \"@type\": \"SearchAction\",\n\t \"target\": {\n\t \"@type\": \"EntryPoint\",\n\t \"urlTemplate\": \"http:\/\/localhost:10008\/?s={search_term_string}\"\n\t },\n\t \"query-input\": \"required name=search_term_string\"\n\t }\n\t ],\n\t \"inLanguage\": \"en-US\"\n\t },\n\t {\n\t \"@type\": [\n\t \"Person\",\n\t \"Organization\"\n\t ],\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6\",\n\t \"name\": \"Aurovrata V.\",\n\t \"image\": {\n\t \"@type\": \"ImageObject\",\n\t \"inLanguage\": \"en-US\",\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/image\/\",\n\t \"url\": \"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/tiffin-dabbawalla.png\",\n\t \"contentUrl\": \"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/tiffin-dabbawalla.png\",\n\t \"width\": 1060,\n\t \"height\": 644,\n\t \"caption\": \"Aurovrata V.\"\n\t },\n\t \"logo\": {\n\t \"@id\": \"http:\/\/localhost:10008\/#\/schema\/person\/image\/\"\n\t },\n\t \"sameAs\": [\n\t \"http:\/\/localhost:10008\"\n\t ],\n\t \"url\": \"http:\/\/localhost:10008\/author\/vrata\/\"\n\t }\n\t ]\n\t}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Mitigating Performance Impact from Personalisation - Tiffin Consulting","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/","og_locale":"en_US","og_type":"article","og_title":"Mitigating Performance Impact from Personalisation - Tiffin Consulting","og_description":"Caching web pages, especially using a Content Development Network is an important step towards a robust and scalable solution. It is possible to cache multiple versions of a page.","og_url":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/","og_site_name":"Tiffin Consulting","article_published_time":"2024-02-02T04:49:14+00:00","article_modified_time":"2024-02-02T12:22:26+00:00","og_image":[{"width":1599,"height":900,"url":"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/fine-tuning-the-machine.jpg","type":"image\/jpeg"}],"author":"Aurovrata V.","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Aurovrata V.","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/#article","isPartOf":{"@id":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/"},"author":{"name":"Aurovrata V.","@id":"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6"},"headline":"Mitigating Performance Impact from Personalisation","datePublished":"2024-02-02T04:49:14+00:00","dateModified":"2024-02-02T12:22:26+00:00","mainEntityOfPage":{"@id":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/"},"wordCount":1313,"publisher":{"@id":"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6"},"keywords":["Lead generation"],"articleSection":["Development"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/","url":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/","name":"Mitigating Performance Impact from Personalisation - Tiffin Consulting","isPartOf":{"@id":"http:\/\/localhost:10008\/#website"},"datePublished":"2024-02-02T04:49:14+00:00","dateModified":"2024-02-02T12:22:26+00:00","breadcrumb":{"@id":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/"]}]},{"@type":"BreadcrumbList","@id":"http:\/\/localhost:10008\/mitigating-performance-impact-from-personalisation\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"http:\/\/localhost:10008\/"},{"@type":"ListItem","position":2,"name":"Mitigating Performance Impact from Personalisation"}]},{"@type":"WebSite","@id":"http:\/\/localhost:10008\/#website","url":"http:\/\/localhost:10008\/","name":"Tiffin Consulting","description":"digital business transformation","publisher":{"@id":"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/localhost:10008\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"http:\/\/localhost:10008\/#\/schema\/person\/e7549052d5ca8cb5891c059c2424a9f6","name":"Aurovrata V.","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/localhost:10008\/#\/schema\/person\/image\/","url":"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/tiffin-dabbawalla.png","contentUrl":"http:\/\/localhost:10008\/wp-content\/uploads\/2024\/02\/tiffin-dabbawalla.png","width":1060,"height":644,"caption":"Aurovrata V."},"logo":{"@id":"http:\/\/localhost:10008\/#\/schema\/person\/image\/"},"sameAs":["http:\/\/localhost:10008"],"url":"http:\/\/localhost:10008\/author\/vrata\/"}]}},"_links":{"self":[{"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/posts\/421"}],"collection":[{"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/comments?post=421"}],"version-history":[{"count":3,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/posts\/421\/revisions"}],"predecessor-version":[{"id":457,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/posts\/421\/revisions\/457"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/media\/424"}],"wp:attachment":[{"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/media?parent=421"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/categories?post=421"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/localhost:10008\/wp-json\/wp\/v2\/tags?post=421"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}