This task is for CentralNotice code to fix the banner bump, that is, the jump in page content due to banners loading and being injected in the background.
The general approach suggested is: for most users, only show banners on their second pageview over the course of a campaign. On the first pageview, we decide which banner (if any) to show on the next pageview, and set a cookie with the requested banner name and some additional data points. On the next pageview, we add the banner to the HTML, either on the server in the cache layer, or very early on during page display.
There are options to consider in two areas for this approach:
1) how to inject the banner; and
2) how to ensure banners are still seen by infrequent users, or users for whom cookie persistence is an issue.
Regarding the first point, how to inject the banner, the options are:
a) Use ESI (edge-side injection) in the Varnish (cache) layer to add banners directly to the base HTML.
b) On the first pageview, in addition to setting the cookie, load banner content into LocalStorage. On the second pageview, on the server, dynamically modify site css based on the cookie, which page display waits on, to reserve space for the requested banner, then inject the banner content from LocalStorage using JS in the ResourceLoader startup process.
On the second point, mitigation for users excluded by pageview+1, options are:
i) Dynamically inject banners on the first pageview for users that seem likely not to return before the campaign ends. This is the simplest option, but will still cause a banner bump for those users.
ii) Chose a banner on the server for such users, based on targeting data points available server-side. This seems feasible since banner selection mostly only considers information stored on the client for frequent visitors.
iii) Start setting cookies on clients a long time before a campaign starts, but only have the cookies trigger banner injection once it starts.
The incomplete, WIP patch currently attached to this task uses option a) ESI for banner injection, and has not yet implemented any measures for pageivew+1-excluded users.
//Notes on the a) ESI approach//
ESI (edge-side injection) would be used in the simplest possible way, in the Varnish layer, to add banners directly to the base HTML.
Banner content would be retrieved via a call to Special:BannerLoader, made from Varnish. Responses from that page would be deterministically based on the contents of the cookie set by client-side code on the previous pageview. The cookie would contain at least the name of the banner to be injected and the campaign associated with it, though it could also be configured to include additional targeting data points, depending on cache capacity. (Those additional data points are not hard requirements for this approach, but they would help make the system fully responsive to changes in campaign and banner settings.)
//Advantages of a pageview+1 approach//
In addition to allowing banner content to be fully deterministic based on cookie content, this method would require relatively little new code, compared to other possible ways of fixing the banner bump, since existing CentralNotice client-side code would continue to do the heavy lifting of banner selection, as occurs in the current system. We would run basically all existing client-side code and would retain all existing features for banner selection, impression limiting, data reporting, large-then-small banners, A/B testing, other banner sequences, banner hiding, etc. From the perspective of client-side code, the main difference would be that, instead of loading and injecting a banner, a cookie would be set to request banner injection by the cache on the user’s next pageview.
//Notes on mitigation//
It's currently not clear what percentage of users who typically click on banners might be affected by an exclusively pageview+1 approach. Initial analysis of a single Fundraising campaign indicates it may be around 10% (see T280478).
Measures should also be put in place for campaigns that **must** show a banner on every pageview (like maintenance or blackout campaigns). This can be implemented server-side.
//(Note: I am working on this on my own time, so, not as part of my work as an FR-Tech engineer. Unless otherwise noted, this task is not included in planned work by FR-Tech. Please consider my contributions here as you would those of a volunteer contributor. Thanks so so much!! - @AndyRussG)//