I don’t think anyone would argue that I’ve written a ton of content over the years about how to get traffic to your website. Still, it’s one of the most important skills to learn. Optimizing your website for conversions won’t matter if you don’t have any traffic to begin with. It’s like expecting to sell merchandise when nobody visits your brick-and-mortar store. Once you know how to get traffic to your website, you can optimize your content and pages based on patterns among your target audience. That’s step two. But as they say, you have to walk before you can…
Have you ever walked into a store, turned around, and walked right back out? You bounced. Maybe you didn’t like the look of the store itself, or perhaps you realized the store didn’t sell the type of merchandise you needed. Whatever the case, you took one look and got out of dodge. The same thing happens on your website, and it’s not a good thing. Learning how to reduce bounce rate makes your site “stickier.” It’s more inviting. Visitors want to hang around for a while — and maybe even buy something or convert on one of your offers. A…
If Benjamin Franklin were alive today, he’d say there are only three things certain in life: death, taxes, and Google changes.
As search behaviour evolves and machines get smarter, Google naturally adjusts what it serves up. And these changes are often quick enough to feel a bit overwhelming (we’re right there with ya)! But in light of information we have about what Google actually values these days, we have more to work with than ever before. If we know how to execute.
Two people who know a lot about Google’s ranking factors are Rob Bucci, CEO of STAT Search Analytics and Cyrus Shepard, Partner at Zyppy and former Head of SEO and Content Development at Moz. Both speakers at this August’s Call to Action Conference, they’re bona fide search experts who spend their time demystifying the ways of our ranking overlords for marketers like you and me.
So we peppered them with a few questions we couldn’t wait until August to find out—like what’s changed, stayed the same, and how to best achieve SEO success in 2018. Get the goods below and learn more about their upcoming talks at CTAConf right here.
Want to get incredible insights from Rob and Cyrus in person? Use the code “CTAConfSEO” at checkout to get 15% off all ticket rates for the conference until July 31.
Rob Bucci on local search and getting snippeted
SEO-obsessed Rob founded STAT Search Analytics, a rank tracking and SERP analytics platform, in 2011. Since then, he’s worked with clients like eBay, Pinterest, Cars.com, and Thomas Cook Airlines to understand their unique search opportunities and win more business.
He’s also a frequent speaker on search, data mining, and all things analytics. In his Call to Action Conference talk, What Google Serves Up For Local Searches, he’ll dive into the nooks and crannies of (you guessed it) local intent, local search, and how to adeptly navigate Google’s interpretations of both to get in front of the right audience. Read below for a peek at what he’ll share on stage.
Hayley Mullen: Your talk at CTAConf is all about interpreting how Google handles local search. So, how are they doing?
Rob Bucci: Knowing that, with location tracking, etc., you can’t always rely on searchers to explicitly state when their intent is local, you need to look at keywords where that intent can be implied. The question then—before you can optimize accordingly—is whether Google is actually any good at interpreting that implicit local intent. And is it comparable to stated local intent?
For example: [sushi near me] would indicate that close proximity is essential; [sushi in Vancouver] seems to cast a city-wide net; and just [sushi] is largely ambiguous—are you hungry for knowledge about sushi or actual sushi? And what happens with a query like [best sushi], which indicates that quality takes priority over proximity?
It’s Google deciding what those queries mean, so it’s important to understand that decision. There’s no point in optimizing for something that Google can’t or isn’t doing. What we’ve found is that Google is doing a decent job of it, and that there are definitely different ground rules when it comes to different kinds of local intent.
HM: Knowing what you do about Google’s interpretation of local intent, what is the biggest mistake marketers can make when it comes to localized ads?
RB: This isn’t a mistake that’s been made, rather, a heads up based on findings from the research I’ll be presenting. But something to keep in mind is that ads are more likely to appear when a location is specified in the search query, like the city name or neighbourhood. So, if you’re looking for less paid competition, it’s a good idea to target keywords that aren’t geo-modified.
HM: Should local search be a priority for everyone? When does it matter more than less, depending on a business’ needs?
RB: For Google, every SERP is a localized one. We know that it’s one of the more influential factors that Google filters its search results through. So, even if local isn’t important for your business, it’s still worth tracking a sample of your keywords in specific locations so you can see what your searchers are actually seeing.
HM: Let’s talk featured snippets. You’ve said they’re rising in importance, appearing in just 9% of searches two years ago compared to 31% by the end of last year. When creating content, what can we do for the best chance at being “snippeted”?
RB: Focus on creating great content and optimizing that content to appear on the first page. At STAT, we’ve found that 99% of snippets are sourced from ranks two through ten, with a majority coming from ranks three through four (when rank one is the snippet).
You’ll also want to research the types of formats appearing in the featured snippets for keywords you’re targeting, for instance paragraph, list, or table, and match them.
HM: Say I only have one day to try and improve my rankings. What should I focus on first to make the biggest impact?
Want even more actionable marketing tips? Read our interview with fellow CTAConf 2018 speaker and product positioning genius April Dunford for advice on successfully launching a new product or offering into a noisy market.
Cyrus Shepard on what matters now for ranking in 2018 (and beyond)
Cyrus Shepard has been in the SEO game for nearly ten years, most recently heading up SEO and Content Development at Moz before founding his own digital agency, Zyppy. He’s written on pretty much every facet of search optimization (check out his Moz profile) and spoken at conferences around the world—with Call to Action Conference up next.
Hayley Mullen: It can feel like Google’s constantly updating its ranking factors. What should always be a priority when we’re trying to rank?
Cyrus Shepard: Google updates its algorithms hundreds of times a year, although only a few of those could be considered major core algorithm updates. That said, the critical SEO success factors stay incredibly consistent. These include:
Content that answers the user query
Content that’s crawlable and accessible to search engines
The quality and quantity of links
HM: What’s been the most significant change in Google’s ranking factors, in your opinion? What do you anticipate for the near and distant future?
CS: The most significant change in the past couple of years, in my opinion, has been the rise of featured snippets. For the first time, we’re actually seeing fewer clicks per impressions as Google is more frequently delivering answers directly in search results.
For websites that win featured snippets, they can often expect more traffic and less visibility. For everyone else, they can expect traffic and visibility to slightly decrease.
HM: Oof—what does that mean for marketers overall?
CS: It’s definitely a dilemma that I don’t have an answer for right now. On one hand, the “no click” search is a growing risk. On the other hand, Google continues to send billions of visits to publishers.
The challenge is that Google maintains monopoly power over search results, so we’re forced to play by Google’s rules and, say, optimize for featured snippets. We continue to give away more data to Google with the understanding that they will reward us with more web traffic, but the amount of data we give keeps rising while Google keeps more of the traffic for themselves.
HM: How much of a difference does speed really make, specifically in regards to AMP (accelerated mobile pages)? What are the top three things we can do to satisfy Google’s need for speed?
CS: Speed is hugely important and not only for AMP. Speed is a huge ranking factor because it impacts so many other elements that impact your search visibility. For example, bounce rate is highly correlated with speed—a site that loads a second slower is abandoned at a much higher rate. This will affect multiple aspects of SEO down the line.
In regards to AMP, they actually have advantages beyond speed that some folks aren’t aware of:
These pages can qualify for Google News carousels
Google marks them with an AMP symbol, which can increase clicks
Chrome pre-renders AMP results, making them load instantly
HM: Your talk at CTAConf is all about what Google’s watching in terms of how people interact with your site. Without giving away the most important point, what’s the one thing Google’s always taking into consideration (and one thing that doesn’t matter as much as we may think)?
CS: Google is likely always evaluating user satisfaction. User satisfaction goes by different names, including task completion, pogo-sticking, dwell time, and more. The basic idea is “does this page answer the user query?” or “does this user need to search other webpages for the right answer?” Exactly how Google does this is up for debate.
A metric that likely doesn’t matter as much as people think is bounce rate. That doesn’t mean it’s not a useful metric—but bounce rate alone doesn’t tell us much.
And with that, our search for answers on search just got a little easier. There’s a lot more knowledge to be shared at Call to Action Conference from both Rob and Cyrus—just two of the many reasons you should totally come!“Use the code “CTAConfSEO” at checkout until July 31, 2018 for 15% off all single, group, and customer ticket rates. You’ll not only learn how to tame the search beast, but hone your chops in every facet of digital marketing too.
Full-day workshop • June 25th
Every day, billions of people around the world use the web to work, to find information, and to be entertained. When they come to your site, they trust you to provide them with a good experience. They expect a site that loads quickly, that works in their browser, and that is well designed. And though they may not vocalize it, they certainly expect that experience will be safe: that any information they provide will not be stolen or used in ways they did not expect.
Today, I’d like to return to a subject that has already been covered in Smashing Magazine in the past — the topic of the print stylesheet. In this case, I am talking about printing pages directly from the browser. It’s an experience that can lead to frustration with enormous images (and even advertising) being printed out. Just sometimes, however, it adds a little bit of delight when a nicely optimized page comes out of the printer using a minimum of ink and paper and ensuring that everything is easy to read.
This article will explore how we can best create that second experience. We will take a look at how we should include print styles in our web pages, and look at the specifications that really come into their own once printing. We’ll find out about the state of browser support, and how to best test our print styles. I’ll then give you some pointers as to what to do when a print stylesheet isn’t enough for your printing needs.
Key Places For Print Support
If you still have not implemented any print styles on your site, there are a few key places where a solid print experience will be helpful to your users. For example, many users will want to print a transaction confirmation page after making a purchase or booking even if you will send details via email.
Any information that your visitor might want to use when away from their computer is also a good candidate for a print stylesheet. The most common thing that I print are recipes. I could load them up on my iPad but it is often more convenient to simply print the recipe to pop onto the fridge door while I cook. Other such examples might be directions or travel information. When traveling abroad and not always having access to data these printouts can be invaluable.
Reference materials of any sort are also often printed. For many people, being able to make notes on paper copies is the way they best learn. Again, it means the information is accessible in an offline format. It is easy for us to wonder why people want to print web pages, however, our job is often to make content accessible — in the best format for our visitors. If that best format is printed to paper, then who are we to argue?
Why Would This Page Be Printed?
A good question to ask when deciding on the content to include or hide in the print stylesheet is, “Why is the user printing this page?” Well, maybe there’s a recipe they’d like to follow while cooking in the kitchen or take along with them when shopping to buy ingredients. Or they’d like to print out a confirmation page after purchasing a ticket as proof of booking. Or perhaps they’d like a receipt or invoice to be printed (or printed to PDF) in order to store it in the accounts either as paper or electronically.
Considering the use of the printed document can help you to produce a print version of your content that is most useful in the context in which the user is in when referring to that print-out.
Once we have decided to include print styles in our CSS, we need to add them to our workflow to ensure that when we make changes to the layout we also include those changes in the print version.
Adding Print Styles To A Page
To enable a “print stylesheet” what we are doing is telling the browser what these CSS rules are for when the document is printed. One method of doing this is to link an additional stylesheet by using the <link> element.
<link media="print" href="print.css">
This method does keep your print styles separate from everything else which you might consider to be tidier, however, that has downsides.
The linked stylesheet creates an additional request to the server. In addition, that nice, neat separation of print styles from other styles can have a downside. While you may take care to update the separate styles before going live, the stylesheet may find itself suffering due to being out of sight and therefore out of mind — ultimately becoming useless as features are added to the site but not reflected in the print styles.
The alternate method for including print styles is to use @media in the same way that you includes CSS for certain breakpoints in your responsive design. This method keeps all of the CSS together for a feature. Styles for narrow to wide breakpoints, and styles for print. Alongside Feature Queries with @supports, this encourages a way of development that ensures that all of the CSS for a design feature is kept and maintained together.
Overwriting Screen CSS Or Creating Separate Rules
Much of the time you are likely to find that the CSS you use for the screen display works for print with a few small adjustments. Therefore you only need to write CSS for print, for changes to that basic CSS. You might overwrite a font size, or family, yet leave other elements in the CSS alone.
If you really want to have completely separate styles for print and start with a blank slate then you will need to wrap the rest of your site styles in a Media Query with the screen keyword.
On that note, if you are using Media Queries for your Responsive Design, then you may have written them for screen.
@media screen and (min-width: 500px)
If you want these styles to be used when printing, then you should remove the screen keyword. In practice, however, I often find that if I work “mobile first” the single column mobile layout is a really good starting point for my print layout. By having the media queries that bring in the more complex layouts for screen only, I have far less overwriting of styles to do for print.
Add Your Print Styles To Your Pattern Libraries And Style Guides
To help ensure that your print styles are seen as an integral part of the site design, add them to your style guide or pattern library for the site if you have one. That way there is always a reminder that the print styles exist, and that any new pattern created will need to have an equivalent print version. In this way, you are giving the print styles visibility as a first-class citizen of your design system.
Basics Of CSS For Print
When it comes to creating the CSS for print, there are three things you are likely to find yourself doing. You will want to hide, and not display content which is irrelevant when printed. You may also want to add content to make a print version more useful. You might also want to adjust fonts or other elements of your page to optimize them for print. Let’s take a look at these techniques.
In CSS the method to hide content and also prevent generation of boxes is to use the display property with a value of none.
Using display: none will collapse the element and all of its child elements. Therefore, if you have an image gallery marked up as a list, all you would need to do to hide this when printed is to set display: none on the ul.
Things that you might want to hide are images which would be unnecessary when printed, navigation, advertising panels and areas of the page which display links to related content and so on. Referring back to why a user might print the page can help you to decide what to remove.
There might be some content that makes sense to display when the page is printed. You could have some content set to display: none in a screen stylesheet and show it in your print stylesheet. Additionally, however, you can use CSS to expose content not normally output to the screen. A good example of this would be the URL of a link in the document. In your screen document, a link would normally show the link text which can then be clicked to visit that new page or external website. When printed links cannot be followed, however, it might be useful if the reader could see the URL in case they wished to visit the link at a later time.
We achieve this by using CSS Generated Content. Generated Content gives you a way to insert content into your document via CSS. When printing, this becomes very useful.
You can insert a simple text string into your document. The next example targets the element with a class of wrapper and inserts before it the string, “Please see www.mysite.com for the latest version of this information.”
content: "Please see www.mysite.com for the latest version of this information.";
You can insert things that already exist in the document however, an example would be the content of the link href. We add Generated Content after each instance of a with an attribute of href and the content we insert is the value of the href attribute – which will be the link.
content: " (" attr(href) ")";
You could use the newer CSS :not selector to exclude internal links if you wished.
If your printed version fits neatly onto one page then you should be able to create a print stylesheet relatively simply by using the techniques of the last section. However, once you have something which prints onto multiple pages (and particularly if it contains elements such as tables or figures), you may find that items break onto new pages in a suboptimal manner. You may also want to control things about the page itself, e.g. changing the margin size.
CSS does have a way to do these things, however, as we will see, browser support is patchy.
The CSS Paged Media Specification opens with the following description of its role.
“This CSS module specifies how pages are generated and laid out to hold fragmented content in a paged presentation. It adds functionality for controlling page margins, page size and orientation, and headers and footers, and extends generated content to enable page numbering and running headers/footers.”
The screen is continuous media; if there is more content, we scroll to see it. There is no concept of it being broken up into individual pages. As soon as we are printing we output to a fixed size page, described in the specification as paged media. The Paged Media specification doesn’t deal with how content is fragmented between pages, we will get to that later. Instead, it looks at the features of the pages themselves.
We need a way to target an individual page, and we do this by using the @page rule. This is used much like a regular selector, in that we target @page and then write CSS to be used by the page. A simple example would be to change the margin on all of the pages created when you print your document.
You can target specific pages with :left and :right spread pseudo-class selectors. The first page can be targeted with the :first pseudo-class selector and blank pages caused by page breaks can be selected with :blank. For example, to set a top margin only on the first page:
To set a larger margin on the right side of a left-hand page and the left side of a right-hand page:
The specification defines being able to insert content into the margins created, however, no browser appears to support this feature. I describe this in my article about creating stylesheets for use with print-specific user agents, Designing For Print With CSS.
Where the Paged Media module deals with the page boxes themselves, the CSS Fragmentation Module details how content breaks between fragmentainers. A fragmentainer (or fragment container) is a container which contains a portion of a fragmented flow. This is a flow which, when it gets to a point where it would overflow, breaks into a new container.
The contexts in which you will encounter fragmentation currently are in paged media, therefore when printing, and also when using Multiple-column layout and your content breaks between column boxes. The Fragmentation specification defines various rules for breaking, CSS properties that give you some control over how content breaks into new fragments, in these contexts. It also defines how content breaks in the CSS Regions specification, although this isn’t something usable cross-browser right now.
And, speaking of browsers, fragmentation is a bit of a mess in terms of support at the moment. The browser compatibility tables for each property on MDN seem to be accurate as to support, however testing use of these properties carefully will be required.
Older Properties From CSS2
In addition to the break-* properties from CSS Fragmentation Level 3, we have page-break-* properties which came from CSS2. In spec terms, these have been superseded by the newer break-* properties, as these are more generic and can be used in the different contexts breaking happens. There isn’t much difference between a page and a multicol break. However, in terms of browser support, there is better browser support for the older properties. This means you may well need to use those at the current time to control breaking. Browsers that implement the newer properties are to alias the older ones rather than drop them.
In the examples that follow, I shall show both the new property and the old one where it exists.
break-before & break-after
These properties deal with breaks between boxes, and accept the following values, with the initial value being auto. The final four values do not apply to paged media, instead being for multicol and regions.
The older properties of page-break-before and page-break-after accept a smaller range of values.
To always cause a page break before an h2 element, you would use the following:
To avoid a paragraph being detached from the heading immediately preceding it:
The older page-break-* property to always cause a page break before an h2:
To avoid a paragraph being detached from the heading immediately preceding it:
On MDN find information and usage examples for the properties:
The Fragmentation specification also defines the properties orphans and widows. The orphans property defines how many lines can be left at the bottom of the first page when content such as a paragraph is broken between two pages. The widows property defines how many lines may be left at the top of the second page.
Therefore, in order to prevent ending up with a single line at the end of a page and a single line at the top the next page, you can use the following:
The widows and orphans properties are well supported (the missing browser implementation being Firefox).
The final property defined in the Fragmentation module is box-decoration-break. This property deals with whether borders, margins, and padding break or wrap the content. The values it accepts are:
For example, if my content area has a 10-pixel grey border and I print the content, then the default way that this will print is that the border will continue onto each page, however, it will only wrap at the end of the content. So we get a break before going to the next page and continuing.
If I use box-decoration-break: clone, the border and any padding and margin will complete on each page, thus giving each page a grey border.
As already mentioned, browser support is patchy for Paged Media and Fragmentation. Where Fragmentation is concerned, an additional issue is that breaking has to be specified and implemented for each layout method. If you were hoping to use Flexbox or CSS Grid in print stylesheets, you will probably be disappointed. You can check out the Chrome bugs for Flexbox and for Grid.
The best suggestion I can give right now is to keep your print stylesheets reasonably simple. Add fragmentation properties — including both the old page-break-* properties as well as the new properties. However, accept that these may well not work in all browsers. And, if you find lack of browser support frustrating, raise these issues with browsers or vote for already raised issues. Fragmentation, in particular, should be treated as a suggestion rather than a command, even where it is supported. It would be possible to be so specific about where and when you want things to break that it is almost impossible to lay out the pages. You should assume that sometimes you may get suboptimal breaking.
Testing Print Stylesheets
Testing print stylesheets can be something of a bore, typically requiring using print preview or printing to a PDF repeatedly. However, browser DevTools have made this a little easier for us. Both Chrome and Firefox have a way to view the print styles only.
Open the Developer Toolbar then type media emulate print at the prompt.
Open DevTools, click on the three dots icon and then select “More Tools” and “Rendering”. You can then select print under Emulate CSS Media.
This will only be helpful in testing changes to the CSS layout, hidden or generated content. It can’t help you with fragmentation — you will need to print or print to PDF for that. However, it will save you a few round trips to the printer and can help you check as you develop new parts of the site that you are still hiding and showing the correct things.
What To Do When A Print Stylesheet Isn’t Enough
In an ideal world, browsers would have implemented more of the Paged Media specification when printing direct from the browser, and fragmentation would be more thoroughly implemented in a consistent way. It is certainly worth raising the bugs that you find when printing from the browser with the browsers concerned. If we don’t request these things are fixed, they will remain low priority to be fixed.
If you do need to have a high level of print support and want to use CSS, then currently you would need to use a print-specific User Agent, such as Prince. I detail how you can use CSS to format books when outputting to Prince in my article “Designing For Print With CSS.”
Prince is also available to install on your server in order to generate nicely printed documents using CSS on the web, however, it comes at a high price. An alternative is a server like DocRaptor who offer an API on top of the Prince rendering engine.
There are open-source HTML- and CSS-to-PDF generators such as wkhtmltopdf, but most use browser rendering engines to create the print output and therefore have the same limitations as browsers when it comes to implementing the Paged Media and Fragmentation specifications. An exception is WeasyPrint which seems to have its own implementation and supports slightly different features, although is not in any way as full-featured as something like Prince.
You will find more information about user agents for print on the print-css.rocks site.
Due to the fact that printing from CSS has really moved on very little in the past few years, many older resources on Smashing Magazine and elsewhere are still valid. Some additional tips and tricks can be found in the following resources. If you have discovered a useful print workflow or technical tip, then add it to the comments below.
How do you know your content marketing is effective? It’s not a rhetorical question, though it may seem like it. While it’s difficult to measure the success and return on investment of content purely quantitatively, you can absolutely use digital analytics to get some directional insights as well as insights that help you improve your approach. The good thing: there are no shortage of tools and guides to help you do that nowadays. The bad thing: it can be a bit overwhelming when you think about how to get started with digital analytics, especially if you’ve got a content calendar…
Each application is a unique challenge to produce in its own right, but even more so when you consider that we have to deploy most projects in manydifferentlanguages. Our content has to work not only on the BBC News and Sports websites but on their equivalent apps on iOS and Android, as well as on third-party sites which consume BBC content.
Now consider that there is an increasing array of new platforms such as AMP, Facebook Instant Articles, and Apple News. Each platform has its own limitations and proprietary publishing mechanism. Creating interactive content that works across all of these environments is a real challenge. I’m going to describe how we’ve approached the problem at the BBC.
Example: Canonical vs. AMP
This is all a bit theoretical until you see it in action, so let’s delve straight into an example.
Here is a BBC article containing Visual Journalism content:
This is the canonical version of the article, i.e., the default version, which you’ll get if you navigate to the article from the homepage.
While the canonical and AMP versions look the same, they are actually two different endpoints with different behavior:
The canonical version scrolls you to your chosen country when you submit the form.
The AMP version doesn’t scroll you, as you cannot scroll the parent page from within an AMP iframe.
The AMP version shows a cropped iframe with a ‘Show More’ button, depending on viewport size and scroll position. This is a feature of AMP.
As well as the canonical and AMP versions of this article, this project was also shipped to the News App, which is yet another platform with its own intricacies and limitations. So how do we do support all of these platforms?
Tooling Is Key
We don’t build our content from scratch. We have a Yeoman-based scaffold which uses Node to generate a boilerplate project with a single command.
Out of the box, this works pretty well for compiling for one platform but we need to support multiple platforms. Let’s delve into some code.
Embed vs. Standalone
In Visual Journalism, we sometimes output our content inside an iframe so that it can be a self-contained “embed” in an article, unaffected by the global scripting and styling. An example of this is the Donald Trump interactive embedded in the canonical example earlier in this article.
On the other hand, sometimes we output our content as raw HTML. We only do this when we have control over the whole page or if we require really responsive scroll interaction. Let’s call these our “embed” and “standalone” outputs respectively.
Imagine doing an equivalent of this for every meaningful DOM interaction in your project. Once you’ve finished shuddering, make yourself a relaxing cup of tea, and read on.
Abstraction Is Key
Rather than forcing our developers to handle these conditionals inside their code, we built an abstraction layer between their content and the environment. We call this layer the ‘wrapper.’
Instead of querying the DOM or native browser events directly, we can now proxy our request through the wrapper module.
import wrapper from 'wrapper';
button.on('click', () =>
Each platform has its own wrapper implementation conforming to a common interface of wrapper methods. The wrapper wraps itself around our content and handles the complexity for us.
The standalone wrapper’s implementation of the scrollTo function is very simple, passing our argument directly to window.scrollTo under the hood.
Now let’s look at a separate wrapper implementing the same functionality for the iframe:
The “embed” wrapper takes the same argument as in the “standalone” example but manipulates the value so that the iframe offset is taken into account. Without this addition, we would have scrolled our user somewhere completely unintended.
The Wrapper Pattern
Using wrappers results in code that is cleaner, more readable and consistent between projects. It also allows for micro-optimisations over time, as we make incremental improvements to the wrappers to make their methods more performant and accessible. Your project can, therefore, benefit from the experience of many developers.
So, what does a wrapper look like?
Each wrapper essentially comprises three things: a Handlebars template, wrapper JS file, and a SASS file denoting wrapper-specific styling. Additionally, there are build tasks which hook into events exposed by the underlying scaffolding so that each wrapper is responsible for its own pre-compilation and cleanup.
scss/wrapper.scss contains wrapper-specific styling that your application code shouldn’t need to define itself. The embed wrapper, for example, replicates a lot of BBC News styling inside the iframe.
Finally, js/wrapper.js contains the iframed implementation of the wrapper API, detailed below. It is shipped separately to the project, rather than compiled in with the application code — we flag wrapper as a global in our Webpack build process. This means that though we deliver our application to multiple platforms, we only compile the code once.
The wrapper API abstracts a number of key browser interactions. Here are the most important ones:
Scrolls to the given position in the active window. The wrapper will normalise the provided integer before triggering the scroll so that the host page is scrolled to the correct position.
Returns the user’s current (normalized) scroll position. In the case of the iframe, this means that the scroll position passed to your application is actually negative until the iframe is at the top of the viewport. This is super useful and lets us do things such as animate a component only when it comes into view.
Provides a hook into the scroll event. In the standalone wrapper, this is essentially hooking into the native scroll event. In the embed wrapper, there will be a slight delay in receiving the scroll event since it is passed via postMessage.
viewport: height: int, width: int
A method to retrieve the viewport height and width (since this is implemented very differently when queried from within an iframe).
In standalone mode, we hide the BBC menu and footer from view and set a position: fixed on our content. In the News App, we do nothing at all — the content is already full screen. The complicated one is the iframe, which relies on applying styles both inside and outside the iframe, coordinated via postMessage.
Tell the wrapper your content has loaded. This is crucial for our content to work in the News App, which will not attempt to display our content to the user until we explicitly tell the app our content is ready. It also removes the loading spinner on the web versions of our content.
List Of Wrappers
In the future, we envisage creating additional wrappers for large platforms such as Facebook Instant Articles and Apple News. We have created six wrappers to date:
The version of our content that should go in standalone pages. Comes bundled with BBC branding.
The iframed version of our content, which is safe to sit inside articles or to syndicate to non-BBC sites, since we retain control over the content.
This is the endpoint which is pulled in as an amp-iframe into AMP pages.
News App Wrapper
Our content must make calls to a proprietary bbcvisualjournalism:// protocol.
A JSON representation of our content, for sharing across BBC products.
Wiring Wrappers Up To The Platforms
For our content to appear on the BBC site, we provide journalists with a namespaced path:
/include/[department]/[unique ID], e.g. /include/visual-journalism/123-quiz
The journalist puts this “include path” into the CMS, which saves the article structure into the database. All products and services sit downstream of this publishing mechanism. Each platform is responsible for choosing the flavor of content it wants and requesting that content from a proxy server.
The AMP renderer does a little magic to render some AMP HTML which references our content, pulling in the /amp version as an iframe:
<amp-iframe src="https://news.files.bbci.co.uk/include/newsspec/15996-trump-tracker/english/index/amp" width="640" height="360">
<!-- some other AMP elements here -->
Every supported platform has its own version of the content:
...and so on
This solution can scale to incorporate more platform types as they arise.
Abstraction Is Hard
Building a “write once, deploy anywhere” architecture sounds quite idealistic, and it is. For the wrapper architecture to work, we have to be very strict on working within the abstraction. This means we have to fight the temptation to “do this hacky thing to make it work in [insert platform name here].” We want our content to be completely unaware of the environment it is shipped in — but this is easier said than done.
Features Of The Platform Are Hard To Configure Abstractly
Before our abstraction approach, we had complete control over every aspect of our output, including, for example, the markup of our iframe. If we needed to tweak anything on a per-project basis, such as add a title attribute to the iframe for accessibility reasons, we could just edit the markup.
Now that the wrapper markup exists in isolation from the project, the only way of configuring it would be to expose a hook in the scaffold itself. We can do this relatively easily for cross-platform features, but exposing hooks for specific platforms breaks the abstraction. We don’t really want to expose an ‘iframe title’ configuration option that’s only used by the one wrapper.
We could name the property more generically, e.g. title, and then use this value as the iframe title attribute. However, it starts to become difficult to keep track of what is used where, and we risk abstracting our configuration to the point of no longer understanding it. By and large, we try to keep our config as lean as possible, only setting properties that have global use.
Component Behaviour Can Be Complex
On the web, our sharetools module spits out social network share buttons that are individually clickable and open a pre-populated share message in a new window.
In the News App, we don’t want to share through the mobile web. If the user has the relevant application installed (e.g. Twitter), we want to share in the app itself. Ideally, we want to present the user with the native iOS/Android share menu, then let them choose their share option before we open the app for them with a pre-populated share message. We can trigger the native share menu from the app by making a call to the proprietary bbcvisualjournalism:// protocol.
However, this screen will be triggered whether you tap ‘Twitter’ or ‘Facebook’ in the ‘Share your results’ section, so the user ends up having to make their choice twice; the first time inside our content, and a second time on the native popup.
This is a strange user journey, so we want to remove the individual share icons from the News app and show a generic share button instead. We are able to do this by explicitly checking which wrapper is in use before we render the component.
Building the wrapper abstraction layer works well for projects as a whole, but when your choice of wrapper affects changes at the component level, it’s very difficult to retain a clean abstraction. In this case, we’ve lost a little abstraction, and we have some messy forking logic in our code. Thankfully, these cases are few and far between.
How Do We Handle Missing Features?
Keeping abstraction is all well and good. Our code tells the wrapper what it wants the platform to do, e.g. “go full screen.” But what if the platform we’re shipping to can’t actually go full-screen?
The wrapper will try its best not to break altogether, but ultimately you need a design which gracefully falls back to a working solution whether or not the method succeeds. We have to design defensively.
Let’s say we have a results section containing some bar charts. We often like to keep the bar chart values at zero until the charts are scrolled into view, at which point we trigger the bars animating to their correct width.
But if we have no mechanism to hook into the scroll position — as is the case in our AMP wrapper — then the bars would forever remain at zero, which is a thoroughly misleading experience.
We are increasingly trying to adopt more of a progressive enhancement approach in our designs. For example, we could provide a button which will be visible for all platforms by default, but which gets hidden if the wrapper supports scrolling. That way, if the scroll fails to trigger the animation, the user can still trigger the animation manually.
Plans For The Future
We hope to develop new wrappers for platforms such as Apple News and Facebook Instant Articles, as well as to offer all new platforms a ‘core’ version of our content out of the box.
We also hope to get better at progressive enhancement; succeeding in this field means developing defensively. You can never assume all platforms now and in the future will support a given interaction, but a well-designed project should be able to get its core message across without falling at the first technical hurdle.
Working within the confines of the wrapper is a bit of a paradigm shift, and feels like a bit of a halfway house in terms of the long-term solution. But until the industry matures onto a cross-platform standard, publishers will be forced to roll out their own solutions, or use tooling such as Distro for platform-to-platform conversion, or else ignore entire sections of their audience altogether.
It’s early days for us, but so far we’ve had great success in using the wrapper pattern to build our content once and deliver it to the myriad of platforms our audiences are now using.
Using heatmaps is like being Jason Bourne. You get to spy on your visitors and see exactly what they’re doing. And, like Jason Bourne, you’re not trying to be evil — you’re just trying to understand what they want. The same is true with SEO. You’re trying to understand what keywords people are searching for to find your business. You need to know what content you can create to drive links and keyword rankings. Essentially, the idea behind both is that the better you understand your audience, the better you’ll be at creating content that meets their needs. And when…
A common Grid Layout gotcha is when a newcomer to the layout method wonders how to style a grid cell which doesn’t contain any content. In the current Level 1 specification, this isn’t possible since there is no way to target an empty Grid Cell or Grid Area and apply styling. This means that to apply styling, you need to insert an element.
In this article, I am going to take a look at how to use CSS Generated Content to achieve styling of empty cells without adding redundant empty elements and show some use cases where this technique makes sense.
Content marketing is the practice of creating a piece of content (generally digital) that is both useful and valuable to certain members of your target market(s).
This piece of content is generally free, though it may be hidden behind a simple email/lead-capture form, and it usually is meant to be found through search or through free/low-budget distribution methods (think social media, low-cost PPC, a small press release).
Some might call this permission marketing, the idea being that your target customers have given you permission to market to them by choosing to access your content.