Google Ads and React.js: Delivering Ads with a Great UX
How to run on-site advertising that provides a seamless experience leveraging your company’s component libraries.
Since the inception of online advertising, users have always complained about the design and relevancy of ads. With the nature of business being to aim for maximum visibility, there is always a dissonance between attention and readability of a website’s content.
As we all know, contrary to print media, there are virtually no technical limitations on the web when it comes to the visual appearance of an ad. Display units in specific have reached a state where some are so extremely annoying that certain committees are even discussing standards for acceptable ads.
Native Ads to the Rescue
Our generation has mastered the art of ignoring such content and the industry has largely caught up on that. Native ads is one of the least invasive measures that fit a publisher’s web experience.
The idea is stunningly simple: Instead of marketing out differently styled content on your website (with overlays and blinking banners probably being the most annoying manifestation of their species), you get to decide what an ad unit looks like. It is then up to the advertiser to provide a copy, among other creatives. Not only is it visually less disturbing — by sharing your app’s look and feel, but a native ad is also very likely to exhibit a better click-through rate.
Native Ads: A Quick Example
To give a quick peek on what Omio’s ad product looks like, have a look at the screenshot below. The ad is distinguishable from the rest of the content both by bearing the “sponsored” label and less functionality compared to the remainder of the result cells.
But it shares the same style and is built using the same frontend components as the rest of the page.
The native ad is intuitive and blends with the entire user experience of the product. If the “sponsored” text wasn’t present, you’d never recognise that result as an ad.
5 Reasons the Status Quo wasn’t enough for us.
Initially, this was pretty much the path we chose to go down as well. Our baseline setup contained an ad slot in our React frontend which was remotely managed by Google AdManager. With as little as some HTML & CSS and some targeting rules based on the user’s search terms, our team was able to run ads on page.
Even though this worked for our first iteration, it just didn’t feel right for a number of reasons.
1.Crafting Pixel Perfect Designs
Building pixel-perfect designs isn’t a superfluity or after-thought. It is to serve the user.
This core value is etched deeply into every product we develop — and the implementation of native ads by mixing some basic HTML and CSS in a confined editor seemed to be doing an injustice to our design philosophy.
Our design team has spent countless hours running user research and building a design system that serves as a common language for all teams in the company. This keeps the entire organization (with a diverse group of teams) on the same page. By leveraging our design system, teams can move faster, communicate better and ultimately increase the speed at which products are released without compromising pixel-perfect designs.
For engineers, a big part of a design system is a library of frontend components. It is more challenging to create perfectly designed native ads without taking advantage of an already established library of components built to reflect a consistent representation of our brand message. A component library not just provides us with pixel-perfect designs, but greatly increases the speed at which we ship ads without having to reinvent the wheel.
More so, when everyone speaks the same language, things get done faster. As a company, a component library lets us speak the same language. Yes, with gruesome engineering hours, we might end up re-creating near-perfect Ads with a WYSIWYG editor, but by completely neglecting our component library, we would be disconnected from speaking the same language as everyone else in the entire company.
To sum up our thoughts on creating pixel-perfect designs, our goal here was to build ads with a great user experience and to do so without breaking the internal means of communication we hold highly within the company — a consistent design system built to promote pixel-perfect designs. This means reusing our frontend component library and delivering a consistent user experience across the entire user funnel, every single time.
2. Speed of Iterations
Iterative and user-data-driven development of software is highly encouraged here at Omio, and as such we’ve built pipelines and processes that enable teams to move fast across the entire company.
Delivering highly performant ads require a lot of tests and iterations to run successful campaigns.
For example, if we went with using the typical WYSIWYG solution, a simple A/B test fostered by a change in design will require communicating with our Ad ops to implement the new design and also tweak the ad campaign set up. This isn’t very efficient.
A more solid approach would be to let our frontend engineers take care of the design implementation, connect this with our A/B test service and letting our Ad ops focus solely on managing the ad campaign. This breeds a division of labour and specialization among the engineering and ad ops teams. All engineering efforts are centralised within the engineering team and the planning, execution, tracking and analytics of the ad campaign is managed solely by the Ad ops team.
This sort of separation of concerns weeds out unnecessary dependencies between teams, a common source of friction when building any product. This leads to faster ads development and release cycles.
3. Versioning and Using a Single Tech Stack
script tag of an HTML panel.
What if your team had spent time building a thriving ecosystem around a specific modern tech stack? A stack that includes release pipelines, preview functionality, modern development experience, and embraces a set of standards and best practices?
As a company, our frontend stack relies on React for creating delightful user experiences. No engineer should be forced to write HTML, and CSS in a WYSIWYG editor when we’ve built a solid infrastructure around our tech stack.
The benefits you get from using a modern tech stack likely outweighs what’s offered by WYSIWYG editors in an ad manager.
Now consider versioning, an integral process in the way software is developed today. When you have multiple developers working on a single application, as is the case in most notable projects, it’s almost impossible to prevent developers from overwriting code changes and breaking each other’s code without a solid versioning system.
With modern versioning systems, a developer can download the current version of the project, work locally and merge their changes without stepping on another developer’s toes. This is important as you can deploy varying versions to different environments such as QA and production, and also work locally in confidence that you’re aren’t jeopardising your colleague’s efforts.
These were strong considerations while designing and planning our native ads implementation. It doesn’t matter what technology stack you use, these concerns remain potent.
We believe that building well-implemented native ads doesn’t mean kicking your current tech stack and development processes out of the window or compromising on a simple yet integral process such as versioning.
When building a global brand, the internationalization of your products is important. It could very well influence the acceptance of your product offering.
If your app / website is available only in English language, you will be cutting off the opportunity to tap into potentially larger foreign markets.
86% of localized campaigns have been found to outperform English campaigns in both click-throughs and conversions.
Internationalization is not a trivial requirement. You need correct translations (preferably by experts/natives), and you need to create a process for which your engineers and copywriters can stay in sync on these translations. For most companies, a process has been tested and currently serves the need of your website/app Internationalization.
Here at Omio, we’ve built a process that leverages PhraseApp service which provides us with instantaneous updates. With internationalization being a core requirement for our product offering, it goes without saying that this was a huge requirement for our native ads as well.
How do you make sure that copywriting and translations are seamlessly integrated into the ad development experience? How do you also ensure that instantaneous updates are received as soon as translations are updated? Most ad manager editors just don’t provide the same level of confidence, communication and reliability you get from a standardized internationalisation process. Regardless of your current internationalization process, you’ll most likely spend ample engineering hours if you tried to replicate this within the confines of an ad manager.
5. Sharing context between the Ad and the Website
Naturally, most ads do not interact with the page itself. They either open a new window or perform a whole page reload once being clicked on.
Hence, one requirement we put on ourselves was:
If our ads are created treated with the same standards as the rest of our product, they should behave like it.
This in turn would mean: They are capable of interacting with the page they are placed on, thus providing a seamless user experience.
Sharing context between a native ad and a parent window sparks interesting engineering challenges.The scope of this article doesn’t permit a full-blown discussion on all the problems encountered and our technical solution to them.
However, the crux of the challenges stems from the fact that native ads powered by an ad manager are typically rendered within an Iframe, and an iframe possesses inherent security limitations set by every browser.
A common clause you’d hear within the tech community is: “use the right tool for the job”. While “the right tool” is sometimes subjective, in some cases the choice is based on the ease the tool provides for solving certain engineering challenges.
For our native ads implementation, we decided we’d have a greater chance of solving this challenge if we used the same tools and services available to us in our day-to-day development processes.
The reason this was important for us is that our native ads aren’t just made of static images and text. They were designed to be highly interactive with the host page, and this poses even more challenges.
Doing this outside the comfort of a standard development process would mean solving difficult engineering challenges with unfamiliar tooling provided by an ad manager. While this may not be the wrong call for everyone, in our case, our judgment was based on reusing the tools we already have in place and making sure we were ready to tackle the challenges that’d come from implementing highly interactive native Ads.
The “right tool for the job” in this case was sticking to tried-and-tested tools we already leverage every day in our day-to-day development. Without going into too much detail, we leveraged the window.postMessage browser API and wired it up with existing redux actions on the frontend. This allowed us to establish a 2-way communication between the iframe and parent. We will post a deep dive into our technical solution in the follow up article.
So far we have seen great initial results which have proven that our users really like interacting with our native ads. Seeing that our tech and product work has paid out is encouraging for us as a team and we will see how we can scale the approach from hereon.
In the next segment we will shed more light on the technical details and the overall setup of the system, so watch this space for the next segment of ads with a great UX!