AMP optimizations

> > Why Google AMP pages are so fast

Created: February 19th 2016

What is AMP?

  • AMP stands for the Accelerated Mobile Pages Project (AMP)
  • AMP is an open source project currently led by Google to make faster mobile pages

Amp optimizations

Rather than describe the AMP project itself, this article will look at the main optimizations AMP uses to achieve faster pages. This article explains in depth why and how pages load so fast using AMP.

Most of these optimizations can be used even if you do not plan to implement AMP and can be considered a stricter than normal set of page speed optimizations.

If you are considering using AMP, these descriptions may help you understand the principles that make AMP work so you can better understand how to accomplish them.

We will be discussing the following principals of AMP:

  1. Allow only asynchronous scripts
  2. Size all resources statically
  3. Don't let extension mechanisms block rendering
  4. Keep all third-party JavaScript out of the critical path
  5. All CSS must be inline and size-bound
  6. Font triggering must be efficient
  7. Minimize style recalculations
  8. Only run GPU-accelerated animations
  9. Prioritize resource loading
  10. Load pages in an instant

1. Allow only asynchronous scripts

This refers to the javascript used or called by your HTML.

If javascript is not deferred or made asynchronous then it will delay the webpage from being seen in a timely manner.

Javascript that is not deferred or async is known as render blocking javascript and is one of the most common page speed issues affecting the web today.

What is Asynchronous javascript?

When a javascript is declared as async, it tells the browser that the execution of this javascript is not important to the page render. The browser then understands that it does not need to wait for this javascript to build the page.

While the page is loading, the javascript may get started, but it does not block the render of the page.

To ensure no javascript is render blocking, AMP does not allow any javascript that is not asynchronous.

Even if you are not using or planning to use AMP, this is a very desirable goal.

How to make javascript async?

In most cases there will be calls to external javascripts that look something like this...

<script src=""></script>

To make that external javascript async we would just add "async" to the call as follows...

<script src="" async></script>

That seems easy, right?

Unfortunately many aspects of a webpage may not work correctly when the javascript is called asynchronously.

Web pages must be built with this in mind, a common example of this might be a library like jQuery.

If there are javascripts that rely on jQuery, that means jQuery must be loaded prior to the javascripts which rely upon it.

In such a case, using async on all the javascripts will result in things being broken or not displaying correctly if at all on the webpage when it loads.

Whether you use AMP or not...

  • A well crafted, performant page would hopefully never rely on render blocking javascript
  • If you have "copy and pasted" javascript into your website from a third party (like an seo tool or analytic tool) you should make sure it can work asynchronously and if it doesn't you should complain to the third party to make it so.
  • If you provide third party javascript for people to "copy and paste" into their websites it should be able to work asynchronously or your tool or service will stop being used by those concerned with pagespeed and web performance (which is just about everyone).

2. Size all resources statically

The Amp documentation describes this by saying...

"External resources such as images, ads or iframes must state their size in the HTML so that AMP can determine each element’s size and position before resources are downloaded. AMP loads the layout of the page without waiting for any resources to download."

This may lead to some confusion because most people reading that would think that an image must state an explicit size like (width=100 height=200) or something like that.

The truth is however that this is not precisely what they mean.

How do sizes work in AMP?

In Amp there are special cases used for ads, images, videos and iframes (things that can mess up the size of a layout). For most cases there are explicit sizes declared for these things but those sizes are used to get the aspect ratio of the item so that they can be rendered responsively.

To illustrate this issue more it would be good to look at the problem they are trying to solve...

When a webpage is being rendered, there are often many style recalculations involved. This means that a great of work is being done that wouldn't need to take place if the browser understood the sizes of something before it was downloaded.

When an image is called from a webpage with no size information, the browser must download the image to know how big the image is.

Once the image is downloaded the browser has to adjust the page to show the image.

  • Browser lays out page
  • Image is called with no size info
  • Image is downloaded
  • Browser gets image size
  • Browser recalculates everything on page to allow image to be seen

If the browser knew the size of the image the above set of steps would be reduced to...

  • Browser layouts page
  • Image is downloaded and displayed correctly in pre-calculated place

By reducing these steps the page can load significantly faster (particularly for pages with many images, ads, etc. in them).

How does AMP do this?

By having special tags like <amp-img> AMP can understand that a declared size of an image is to used as a guide rather than an absolute strict and explicit size that the image must be displayed as.

How can this be done without AMP?

This can be achieved by having a planned responsive image solution. Using srcset is becoming more and more supported by browsers.

Whatever technique you do use don't forget this very simple and underutilized no brainer:

If an image is less than 50 pixels or so, it is likely fine to just explicitly size it using width and height.

This will work out for a surprising amount of your images. If we use the page you are reading now as an example - my authors photos are explicitly sized using height and width in the image tag. This is because they are small enough that they wont really be reduced by a browser.

If images are not displayed under a certain width than you can likely more explicitly state image sizes here too.

Lets say we have a sidebar that only displays if a page is wider that 1000 pixels. If the images in that sidebar are planned in a manner where they are always the same size regardless of how much wider the screen gets, then there is no reason not to add a good old fashioned width and height to them.

3. Don't let extension mechanisms block rendering

This is another example of the recurring theme of optimizing the critical rendering path.

What are extension mechanisms?

In the AMP documentation the examples that are used are lightboxes, instagram embeds and tweets.

Extension mechanisms use some portion of a layout to display unknown things in them which will require additional HTTP requests.

These sorts of things often cause the same issues as images do when it comes to the size in which they will be displayed and unlike an image, there will likely be much more complicated things going on as far as layout goes.

Ideally the http requests for the layout and content found in such things should not block the rendering of the page.

In other words, the webpage itself should be rendered first, and only after that should these other things be worried about. An example is a webpage with an ad. The webpage should load first, then the ad. The webpage render should not have wait for the embedded things.

How is this handled in AMP?

In AMP this issue is resolved by calling a script that is aware that a special tag found within the HTML will be included.

An example would be that if a webpage will have an iframe in it, then the amp-iframe script is called in the head which will be aware that an amp-iframe tag will be in the HTML so that it can create the iframe box before it is even aware of what it will contain.

How to handle this without AMP?

Good planning and deferral.

This same type of optimization can be achieved by deferring such things out of the initial page load.

By deferral, I do not mean adding a "defer" to your javascript.

I mean deferring anything not required for the initially visible content outside the page load itself. I do this on the page you are reading and every page on uses this technique.

  • Are images initially visible? If yes - call them. If no - defer them.
  • Is the twitter widget in your footer initially visible to a user? No (because it is in your footer) - Defer it.
  • Is your lightbox initially visible to a user? If not - defer it.

What is this defer thing?

Deferring things is the act of making things wait until the onload event.

This means basically, let the page load, then (and only then) let other things happen.

I have written about deferral techniques extensively...

Anything deferred using the above tecniques will not block render at all.

4. Keep all third-party javascript out of the critical render path

Yet again, another optimization to the critical rendering path (which really is the most important concept in page speed).

Third party javascripts are typically the result of copy and paste solutions for things like social buttons, analytics, seo tools, marketing tools, ads, and so on.

Third party javascripts tend to not be very considerate to the end user.

By blocking all third party javascript, AMP frees a webpage to render without waiting for anything else except what is absolutely required to display the visible part of the page.

The reason to pay special attention to third party is because the webmaster does not have control of what the script is doing.

Often the script will use synchronous calls or document.write, both of which will block render significantly.

The AMP documentation describes an illustrative example:

"...If you have five ads, and each does three sync loads, with a 1 second latency connection, you’re in 18 seconds of load time just for JS loading."

So clearly third party javascripts must be controlled.

Can third party javascript be used in AMP?


Custom / third party javascripts can only run in sandboxed iframes.

What is the problem AMP tries to solve with this optimization?

Third party and custom javascript often create problems that significantly affect page load times.

How does AMP deal with this issue?

AMP restricts the way such javascripts can behave by allowing them only to run in iframes that are sandboxed (kept from interfering with the page itself).

This means that they will not affect the critical rendering path, and the initial page load.

It also means that since the iframe environment is a much smaller thing that the entire page, the style recalculations will be much smaller as well.

How to deal with this issue without using AMP?

The most important thing you can do is to ensure that every third party javascript your page is calling is actually being used. Many times snippet of code are left behind that are not doing anything. Maybe you or someone else was testing a tool, decided not to use it, but left the code snippet by mistake.

Do an inventory of your externally called javascripts by using the Varvy javascript tool.

Once you are sure you are actually using the things you are calling, you can now try to optimize them.

Try to async or defer the remaining javascripts and see if your page still functions correctly.

If you find that these methods do not work for you, contact the third party and ask them if they have a solution for taking their product out of the critical rendering path.

If they do not have a solution, you will likely need to replace them with a similar product that prioritizes web performance.

5. All CSS must be inline and size-bound

In short, CSS can not be larger than 50k and must be inlined into the HTML.

This means if you are using a CSS framework you may have to change your ways.

Remember, all css is render blocking. This means nothing at all can be displayed in a browser until the CSS is dealt with.

CSS frameworks often call hundreds of kilobytes of CSS.

To go AMP, you will actually have to write CSS for the page itself, rather than for the whole site.

This page as an example

I really like my design. It looks nice, is responsive, and it even has big images using SVG and animations. Guess how big the CSS is for the page you are reading right now?

Varvy articles use less than 4kb of CSS

Yes, that is right. 4k. Since that CSS is inlined, it gets reduced even more because I have compression enabled.

This is a great example of using AMP optimizations without actually using AMP.

When you make CSS only for the page it is on, it is pretty amazing how small it can get.

To see how much CSS your pages are using try the Varvy CSS tool.

CSS for most sites, particularly sites using frameworks, are a big giant mess that typically use less than 5 to 10 percent of the CSS it loads.

Bootstrap, Foundation and other such CSS frameworks are not really the way to go anymore.

If you have a designer that says they have to use a framework, I would suggest you do not hire them.

Frameworks only help designers, they actually cause harm to the company paying the designer by creating bloated code that slows down their web site.

CSS is an important issue. I think that restricting CSS to under 50k is a wonderful optimization for the web, and a very desirable and achievable goal for any webpage.

To learn more about the challenges and solutions of CSS, please see my CSS delivery optimization article.

How does AMP restrict CSS size?

It does so by setting a hard limit on the CSS size (50k). AMP enforces this by ensuring any page that has more than 50k of CSS will not validate and therefore will not work using AMP.

How to do this without AMP?

The best thing (and the most difficult thing) you can do to make your website faster is to use CSS wisely.

The real answer here is to only use CSS that is needed for the page.

In most cases the CSS that is need for the entire site is loaded for every pageload.

Using a typical wordpress template as an example, to load one page requires:

  • All comment CSS (typically dozens or even hundreds of lines) must be loaded to see any page - even if no comments are used on that page.
  • All plugin CSS must be loaded to see any page - even if the page isn't using that plugin or even if the plugin is something for admin reason that no user will ever see
  • All additional style templates (example: dark theme, light theme, etc.) must be loaded to see any page - even if entire site is not using that template style

Hopefully you get the picture, but if you are using a CSS framework like Foundation or Bootstrap, it is very likely that no one page uses more than 3% to 8% of all the CSS you are loading.

To change this is not a simple task. It can cost a great deal of money and time.

If you are doing a redesign, make sure that you are not using large CSS frameworks. They simply will not work for AMP or the modern web.

When every page is only using the CSS it needs for that page, there wont be many reasons to go over 50k.

6. Font triggering must be efficient

In a typical webpage, many js and css files are loaded before the font is.

This is bad for pageload times because font files are typically quite large, whereas the js and css files are less large.

The common sense solution is to have the font file start loading before all other files so that the resource will be downloaded with as little delay as possible.

The problem is there is no real way to make this happen without hacks or inlining the entire font to the HTML (as I do on this site).

AMP files are planned and created from the very first line of code to load incredibly fast.

One of the primary considerations of AMP is how to deal with webfonts optimally.

The basic ways that browsers deal with webfonts are all less than ideal, so AMP employs a hack to take care of this problem.

How does AMP make font triggering efficient?

It uses a hack. The hack needs javascript to work best, but has a fallback.

The hack itself has already changed and we have been told it will likely continue to change, so rather than define the hack, let's just describe what the hack does.

The goal is to override the way browsers deal with webfonts.

More specifically, the goal is to ensure that the font request is the first HTTP request that occurs.

AMP basically tricks a browser into thinking that the page is loaded enough to download the font.

By doing this AMP ensures that load times are not delayed by the typically large font file.

Rather than the CSS and Javascript files loading first, the font does.

How to do this without AMP?

The main way is to inline the webfont into the HTML. The page you are reading now has the font inlined.

Unfortunately there can be many drawbacks to inlining font into HTML:

  • If not done expertly, the size of the HTML file can become too large
  • It is only feasible if only one font / font variant is used on page
  • It can leave out important international characters that may or may not mess up depending on where page is seen
  • It can only really occur on an extraordinary performant page

To understand how to inline a webfont (and the different methods you can use to implement webfonts) see my webfont options page.

In any case webfonts must be used wisely:

  • If a page is not using a webfont, do not load it.
  • If a page is not using the "bold" variant of a font, do not load it.
  • Do not have your overall design depend on having several fonts / font variants on one page.

I have inlined my webfonts for this site for over a year now over several millions of pageloads I have not had issues that would make me consider not doing so.

This has been possible because I designed this site ground up to require only the HTML file for the above the fold content. Every page on Varvy has everything above the fold, including the font, inlined into the HTML file (no additional HTTP requests are needed to display initially visible content).

7. Minimize style recalculations

What is a style recalculation?

When something changes or needs to be measured on the webpage that affects layout, the entire page must be recalculated even for minor changes.

We spoke a little about this above using images as an example, let's revisit that with an admittedly oversimplified situation.

If an image does not have a size declared, then the image has to be downloaded just to find out how big it is.

Let's say a page has a 500px height with one image of unknown size. When the image is loaded, the browser discovers that the image is 600px high.

This situation would clearly require a style recalculation.

When these recalculations happen, they create many issues as far as page speed goes.

But it is not just images, many divs, on your page may have a css style that uses a percent. Maybe you have two columns each with a width of 50%.

The browser has to figure this out and the process of doing so is called layout.

Layout has to figure out many things, just think about font-size, h1, h2, divs, images, all those page elements need to be recalculated several times in a typical page load.

Why does this happen?

There are many reasons, perhaps new info is loaded like an embedded content block or ad. Sometimes external javascript might call in new styles or animations. Or back to our simplest example, an image without a size declared.

Whatever the cause, style recalculations are bad.

They get worse when you consider an average website using a CSS framework might have nearly half a meg (500k) of CSS to go through and recalculate.

The more CSS the more costly in terms of time and effort the recalculation.

AMP has the goal of nearly eliminating these recalculations.

Using just the optimizations we have discussed so far in this article, you can see that many recalculations are eliminated:

  • In AMP sizes must be declared statically. - removes style recalculations
  • In AMP there needs to be less that 50k of CSS. - removes style recalculation cost

AMP actually goes above and beyond these type of optimizations as well.

How does AMP minimize style recalculations?

In addition to the general optimizations we discuss in this article, AMP also ensures that all DOM reads happen before the writes.

This means there does not have to big a big mess of recalculations for every frame, in fact it ensures there is a maximum of one recalculation per frame.

How to do this without AMP?

The best way to minimize style recalculations is to follow the optimizations we are discussing in this article. As mentioned above, each of them are essentially removing complications and layout issues by their very nature.

Saying "minimize style recalculations" is pretty much the same thing as saying "plan your page well"

When a page is made as a page, rather than as a website, these things tend to work themselves out.

What I mean by that is that just like CSS should made for the page it is on, rather than the entire website, so should everything else.

  • Javascript files? If not used on the page do not load it.
  • Images? Plan your images for the page, not the site - do not have a site-wide image solution that covers all scenarios, plan it page by page (or page template by page template) - declare the size when possible.
  • Embeds? (like social buttons) If you are not showing the button on the page, do not have the code or calls for the button on the page.

The above things seem like common sense but virtually every WordPress site on the web does those very things.

To minimize style recalculations you must know what is happening on that page. It does not matter what your site needs, it matters what that page needs.

People do not look at sites, they look at pages.

Make the page better for the user, rather than making your site easier for your designer.

8. Only run GPU accelerated animations

The use of animations is becoming ever more popular and widespread. When I say animations you may think of the large moving images like you find at the top of my articles. The truth is however animations are used in so many places for small things for user interface acknowledgments and other such things. If you get a WordPress theme that was built recently, it likely has animations in it.

In order to make sure our animations are AMP friendly, we must ensure that the animations can be handed off to the GPU.

What is a GPU?

GPU stands for Graphics Processing Unit.

Unlike the CPU (Central Processing Unit), the GPU is there specifically for the math required by animations. Because of its' specific nature, the GPU is very good dealing with graphic animations.

This benefit becomes even larger because since the GPU can do the animation math, it frees up the CPU to do the job of rendering the page more efficiently because it doesn't have to do all the animation math.

Long story short, the CPU and GPU can render cleaner and faster animations together than when the CPU alone is used.

How does AMP ensure animations are GPU enabled?

Unfortunately there is no simple command that just says "Use the GPU for animations".

What can be done, whether you use AMP or not, is to restrict animations to using two methods...

  • Transform
  • Opacity

AMP restricts animations to these two methods (which can be used to make most animations work) and promotes the element to be animated.

How do I do this without using AMP?

In the exact manner which AMP does it.

  • Restrict animations to transform and opacity
  • Promote the animation element

The restricting animations to transform and opacity is a simple concept, while the "promote" part might seem new and takes care and planning to use correctly.

The Google developer page that explains the method gives a good overview of the process.

9. Prioritize resource loading

Page resources can be images, ads, embeds, etc.

In a typical webpage these resources are often loaded in such a way that they are fighting for the same bandwidth and there is no easy way to know which resources will load before another.

Sometimes even well thought out pages still encounter this problem.

The truth is however, most pages are not well thought out and resource loading is a common and significant issue of page speed in general.

An example of this might be where several third party scripts are loading and because they are loading some things that should have been loaded first doesn't and the user does not see it initially as they should.

We discussed this same problem above in the font triggering section. In fact, fonts illustrate the problem well. When the font is loaded after other resources it cause additional delay to the user seeing any text at all. Not because the font is too big, but rather because the font was loaded out of order.

How does AMP take care of this?

The AMP documentation states:

"AMP controls all resource downloads: it prioritizes resource loading, loading only what’s needed, and prefectches lazy-loaded resources."

The manner in which resources are loaded is key to how fast the page loads.

The same web page, with the same content, using the same images, css files, js files and the exact same font will load at different speeds depending on the order in which those resources are loaded.

I work with many startups and established businesses who have overloaded their pages with third party scripts and I clean up their pages and the way their resources load and often can make a fifteen second page load in 3 or 4 seconds.

They are typically amazed by that.

AMP does the same thing I do with those websites, it intelligently loads resources.

An over simplified example can be that a page that loads css before javascript is typically faster than a page that loads javascript before css. If that page also defers images below the fold, defers js that is only need below the fold then seconds can be removed from the page load time.

AMP essentially forces some best practices.

AMP also attempts to go further by prefetching lazy loaded resources.

That might sound odd at first, why would it prefetch a resource that was explicitly lazy loaded?

I am going to state this pretty informally: there are sorta three things a browser is doing when a webpage is loading...

  • getting stuff
  • doing stuff
  • doing nothing

As simple as those sound, they are the key to intelligent resource loading.

  • While the page is "getting stuff" it should be getting as little stuff as possible to display content to the user
  • While the page is "doing stuff" it should do as little as possible to display content to the user
  • While it is "doing nothing" is a great time for it to do things that will soon be needed

The issue with most webpages today is that everything is crammed together at once.

Everything is called for at the same time "getting stuff" which means that everything will be received at once which really complications the "doing stuff" part because now it has to do a million things at once.

Yet there is massive window of opportunity when the browser is "doing nothing".

AMP simply uses these windows of time intelligently in a manner which allows the page to load efficiently.

How do I do this without AMP?

The truth is that you do not need AMP or any other thing to prioritize resource loading.

There is a process you can follow in general that will help your pages load faster with the same resources.

  1. Understand the critical rendering path
  2. Optimize CSS delivery and load CSS first
  3. Make a list of every resource your webpage loads
  4. Split those resources into two groups: one group is "above the fold" things and the other group is below the fold things.
  5. Defer things that are below the fold (If images are not visible above the fold, those images should be deferred if you have things in your footer that use javascript or external calls, defer those because your footer is not likely to be seen above the fold).
  6. Consider if you truly need everything you are loading for that specific page. If not, get rid of it.
  7. Make sure you are following the page speed best practices

The truth is, as Google acknowledges, is that pages that are hand tuned well can be much faster than AMP pages.

The page you are reading right now would be slower if I used AMP than it is now mainly because of the way I use resources.

10. Load pages in an instant

AMP uses preconnect to prerender to achieve webpages that load extremely fast (pretty much instantly).

What is preconnect?

Officially it is:
"The preconnect link relation type is used to indicate an origin that will be used to fetch required resources. Initiating an early connection, which includes the DNS lookup, TCP handshake, and optional TLS negotiation, allows the user agent to mask the high latency costs of establishing a connection."

Let's break that down a little... preconnect is a way to tell browsers:

"Hi, I just thought you should know that we will be requiring this resource soon, so why don't you go ahead and start connecting to it."

By doing this, browsers can decide when it is most optimal for it to make that connection.

This will allow the resource to be ready to go when it is needed because all the network details are already done (dns/handshake/ssl)

What is prerendering?

With prerendering, you are actually telling the browser to to act as if it is building and displaying a webpage by downloading the html, the resources, building the DOM, the CSSOM and doing the layout.

When a page is prerendered, it will show up instantly to the user in most situations because the browser has already done all the work.

Preconnect, prerender, and some other browser hints such as dns-prefetch all have a common issue.

They are often misused.

They sound so neat! "Let's just prerender everything!" People think but... the problem is you can actually cause your pages to load slower, use more cpu / battery resources and also mess up your stuff pretty bad when these hints are misused.

How is this used in AMP?

AMP uses prefetching and prerendering in a more intelligent way.

Rather than just prerendering everything, it will only prerender above the fold content and resources, and since the AMP system is predictable, the whole prerendering thing just works much better via AMP.

AMP pages also go a step further by refusing to to prerender things that will take too much CPU cycles, or even things that thay may use too much CPU like third party iframes.

How to achieve this without AMP?

The use of preconnect, dns-prefetch, and prerendering can be done without AMP.

I have found it a slippery slope, and I rarely do it for those who hire me.

There do exist situations where they offer incredible benefits, but those situations are rarer than you may think.

I do not use "pre" anything on Varvy. I have found that when a page gets truly optimized, the need for prerendering kind of just goes away.

To use this article as an example:

  • The font is inlined
  • the CSS is inlined
  • I use only one inlined js
  • Above the fold images are inlined as well

There are no resources to prefetch, render or anything else because as long as a browser has the html file, it has everything it needs to display the page.

I find this to be a good strategy that has replaced my need for browser hints such as prefetch or prerender.

If your webpages rely on a great deal of resources, I have found that reducing or optimizing the way your resources load is a better strategy more worth your time than using prefetching or loading.

Time spent on optimizing and fine tuning your page load is time well spent and benefits your entire system.

AMP optimizations are not just for AMP

Throughout this article I have tried to show that AMP optimizations can be used by anyone with or without actually using AMP.

To be fair to AMP though...

AMP also has special caching and a Google supported CDN behind it.

That is a very powerful motivation to use AMP with many benefits.

To be fair to AMP naysayers....

Amp is fundamentally a system that just enforces certain page speed rules that can for the most part be achieved without using AMP.

AMP pages add complexity and must be learned. Some say it is better just to learn the right way to do things and just... do things right.

What do I (Patrick Sexton) personally think of AMP?

AMP does not benefit me because my site (the one you are reading now) loads faster without AMP.

This means that for me personally it does not offer promise.


Startups and established businesses hire me to make their sites faster.

Nearly every business I work with have the same issues (third party scripts for things like forms, seo tools, analytic tools, marketing tools, etc.) and I am absolutely delighted about the future possibilities of AMP particularly when it comes to having a unified system for things like analytical data.

I also love that the attention AMP gets is another nail in the coffin of third party tools providing non performant code to their users.

In the last year or so I have seen some of the biggest names on the web lose some massive clients because their code options are so poor and do not consider performance as a priority.

I believe that the people who will get the best bang for their buck out of AMP will be those who must interact with other content as part of their platform. Think of Facebook showing articles, Twitter, Pinterest etc. as all of these companies are based mostly upon sharing other content that comes from other sources.

As such, AMP provides an excellent advantage for them. The other group of companies that will benefit from AMP a great deal is obviously news and current event publishers who would like to have places like Facebook, Twitter, Pinterest, etc. use their data.

Faster pages

However you achieve it, making your pages faster means more satisfied users, more profit, and a better internet for all.

Patrick Sexton by