Coronavirus’s impact on mobile ad spend and monetization (the data version)


Coronavirus’s impact on mobile ad spend and monetization

Have you stocked up yet? 🤔

We have seen cities, even countries like Italy in lock down mode right now and millions of people are affected. It has become a global pandamic which not only has dramatic effects on people’s lives (think work from home and the Netflix-and-quarantine life style) but also on the global economy. 

And this leads to a thought about our own industry – adtech. How would this pandemic affect mobile ad spend and ad revenue. If revenues are in free fall given the stock market performance and other factors, big spenders’ marketing dollars might be budgeted in for later. However, AppMonet noticed that our publishers are actually in an entirely different situation. We serve ads mostly for self care, self education, casual games and news & entertainment apps. These industries will probably even benefit from this crisis. AppMonet saw at least 10% more app bid requests in the past few weeks compared to December. It is evident that mobile usage has been going up during this period. 

And according to Apptopia’s data, we saw significant increase of usage and installs on work from home and online education apps. In addition, as you can imagine, people who are quarantined need to be entertained. Sessions of China’s top streaming video apps were slowing but experienced a rebound as the severity of the virus increased. And in South Korea, the usage of Netflix soared. 

So publishers, what can you do to succeed during the turbulent times? There are two sides – user acquisition and app monetization. It seems to be the time to scale budgets in countries that have been hit hard by coronavirus – at least for those apps that benefit from people in idle mode. We have seen a declining CPM in terms of acquiring users because many big players have put a pause on marketing spend (reference).

On the app monetization side, the first and foremost, even if your entire office is working from home, make sure your app is working! Make sure there’s no issue with your server or services so that people can enjoy using your apps with no interruptions! More importantly, it’s time to optimize your monetization strategies. If you rely heavily on ads, it is time to optimize your ad placements and units, your eCPM, and the mobile ad network partners you choose to work with. 

AppMonet connects developers with the largest brand advertisers for higher revenue. Being in the center of NYC, AppMonet has harnessed relationships with the largest brand advertisers and agencies which created unique brand demand. With one unified SDK, AppMonet supports all major video brands while maximizing and diversifying apps’ brand advertising demand sources. We have been a trusted partner for many world renowned apps and we are certainly here to help! Get in touch today if you are looking to make higher revenue for your apps!

Drive revenue and boost engagement. Find out how.

Read more

What apps can do to get a boost from increasing stay-home activities during the Coronavirus outbreak?


What apps can do to get a boost during the Coronavirus outbreak?

Before we start, lysol your phone please. 

In hard-hit areas that Coronavirus has widely spread, increasing people are confined to their homes. Employees will be working from home and students are taking classes via live streams. During the coronavirus outbreak last month, app usage in China has surged during the period when major cities were locked down. People are turning to games or socializing online for a sense of camaraderie and to help pass the time. Total game downloads on Apple’s app store in China increased 27.5% year over year and revenue rose by 12.1%, according to market research firm Sensor Tower. Douyin, China’s TikTok grew by 102% as bored teens went to cloud raves, created humorous videos about their isolation. Video games such as PUBG by Tencent saw a significant increase in playing time and in-app spend. 

While more people are stranded at home instead of traveling or socializing outside of the home, smartphones offer a way to connect with friends, alleviate boredom, or find crucial information on the Coronavirus outbreak. So what can your apps or games learn from Chinese apps’ success during the Coronavirus outbreak? AppMonet has put together a few key strategies to help you better engage your users and give them a peace of mind. 

  • Make your app free or extend your promotions 

Many Chinese video game companies have responded to the coronavirus outbreak by extending or introducing new promotions. Some games even changed their business models to make the games free with the option to make in-game purchases, as noted by Omdia, a tech research service. Make your users happy, help them connect for a much-needed dose of human contact, your sales would be soaring as people locked up in quarantine would pounce on anything to keep the blues of isolation away.

  • A friendly reminder conveys your company value

If you are a news or information related app, make sure you prioritize your information related to the Coronavirus virus so people would turn to your app to check the latest updates on Coronavirus. Even if you are not in the news/information category, a friendly reminder/push notification on following good respiratory hygiene shows you care about your users and reflects good company values. 

  • It’s time to optimize your in-app advertising 

With increasing time spent in the app, it’s time to think about how you could maximize your ad serving. Mobile advertising has now overtaken in app purchases as the primary money maker for app publishers. In-app banners and video ads are great ways to monetize your app but you need to be smart about the mobile ad network you decide to partner with. In addition, think about the ad formats that best fit your apps. In-app ads don’t have to be intrusive or pushy — when ads are highly targeted and present the right offers to the right users, they can add value for both the advertiser and the user. The wide variety of ad formats allow apps to accommodate the user experience in a way that isn’t disruptive.

With unparalleled 3rd party verified viewability rates, unique video pre-caching technologies, rich media formats, and extensive SDK footprint in the top apps worldwide, AppMonet is dedicated to help you monetize your users without compromising on user experience. If you are interested in chatting more about your app monetization strategy, get in touch today!

Stay calm and wash your hands!

Drive revenue and boost engagement. Find out how.

Read more
AppMonet is a member of the Interactive Advertising Bureau (IAB)

Press Release: AppMonet Joined IAB Europe’s Transparency and Consent Framework 


AppMonet Joined IAB Europe’s Transparency and Consent Framework 

AppMonet is a member of the Interactive Advertising Bureau (IAB)
AppMonet is a member of the Interactive Advertising Bureau (IAB)

New York, NY, Feb. 18, 2020Today, AppMonet announced our approved status as the latest VENDOR to join IAB Europe’s Transparency and Consent framework (the Framework).

The framework, which was launched in April 2018, is designed to help all parties in the digital advertising chain ensure that they comply with the EU’s General Data Protection Regulation (GDPR) and ePrivacy Directive when processing personal data or accessing and/or storing information on a user’s device, such as cookies, advertising identifiers, device identifiers and other tracking technologies.

The Framework was developed by IAB Europe in collaboration with organizations and professionals in the digital advertising industry. It provides transparency to consumers about how, and by whom, their personal data is processed. It also enables users to express choices. Moreover, the TCF enables vendors engaged in programmatic advertising to know ahead of time whether their own and/or their partners’ transparency and consent status allows them to lawfully process personal data for online advertising and related purposes. 

Through the Framework, publishers can continue funding themselves through relevant online advertising, and brands can continue to reach their audiences. All the while and most importantly, consumer privacy is protected. 

AppMonet believes that the IAB framework is the best way for everyone — advertisers, publishers, and consumers — to be on the same page concerning GDPR and consumer consent. The added registration of AppMonet to the Framework, further bolsters IAB Europe’s mission to raise the standard and trust in digital advertising across Europe. 

Drive revenue and boost engagement. Find out how.

Read more
background image for AppMonet Newsletter sign up

Meet Our New and Improved Dashboard


Meet Our New and Improved Dashboard

AppMonet, a trusted mobile ad network, is excited to announce the launch of our new dashboard, which is now available to all AppMonet publishers! The new dashboard was built with our 200+ publishers at top of mind, taking into account the leading metrics and reports that our publishing partners have generated in 2019. Our goal is to give them a clear overview of all of their activities on the AppMonet platform, and increase the amount of control that they have. 

What you will see on the new dashboard

The publisher dashboard is comprised of in-depth and intuitive, charts, tables and graphs. They map out the main metrics and data points AppMonet publishers use on a daily basis. The key metrics include Clicks, Bid Responses, Requests, Impressions, Efficiency, CTR, Bid CPM, Winning CPM, Revenue, Fill Rate. It can also be customized to any timeframe and filters including Demand Partner, Creative Type, Country and Ad Unit. 

For any feedback or questions about the dashboard, please reach out to

Drive revenue and boost engagement. Find out how.

Read more
Using Closure Compiler With Webpack + Typescript via Tsickle

Using Closure Compiler With Webpack + Typescript via Tsickle

Using Closure Compiler With Webpack + Typescript via Tsickle

Using Closure Compiler With Webpack + Typescript via Tsickle


Written by Nick Jacob

At AppMonet we serve hundreds of terabytes of javascript each day to tens of millions of devices. Our SDK is deployed in hundreds of top apps; sometimes in multiple apps on the same phones. It’s critical that we minimize our the impact of our SDK — ads should consume as few resources as possible.

Javascript bloat plagues the open web; the average webpage has 350kb of gzipped Javascript (Addy Osmani has an awesome talk about why JS file size is so problematic on mobile). Because AppMonet is mobile-only, we’re especially sensitive to the size of our Javascript files—besides lower network speeds, we’re also running in resource-constrained devices with slow javascript runtimes (Android pre-lollipop, iOS UIWebview).


The closure-compiler used to require running a jar (wrapped by a node module)—it’s now also available as a native binary or pure-javascript library, giving much better compile times.

In a lot of cases, closure compiler is similar in performance to uglifyJS/terser—especially if you’re able to mangle properties in uglifyjs. However, there is a special mode—ADVANCED_OPTIMIZATIONS that is really the holy grail of javascript optimization. From the closure compile docs:

The ADVANCED_OPTIMIZATIONS level compresses JavaScript well beyond what is possible with other tools.

Closure Compiler Compilation Levels | Google Developers

The Closure Compiler lets you choose from three levels of compilation, ranging from simple removal of whitespace and comments to aggressive code transformations. The WHITESPACE_ONLY compilation level removes comments from your code and also removes line breaks, unnecessary spaces, extraneous punctuation (such as parentheses and semicolons), and other whitespace.

Unfortunately using it isn’t so easy—if you read the closure compiler docs about ADVANCED_OPTIMIZATIONS, you’ll see that you not only have to carefully declare all of your “externs” (anything that can’t be mangled beyond recognition), but alsoannotate all of your code with jsdoc-like comments to achieve maximal performance.

These comments are a very es3-centric way of expressing types:

 * A shape.
 * @interface
function Shape() {};
Shape.prototype.draw = function() {};

 * @constructor
 * @implements {Shape}
function Square() {};
Square.prototype.draw = function() {

But if we’re using typescript, doesn’t our code already contain all of this information about types and visibility? If we could convert typescript to this annotated javascript, we’d be able to use ADVANCED_OPTIMIZATIONS without any changes to our code!

Luckily, the angular team has developed a tool called tsickle, which does exactly that! From the tsickle github:

* inserts closure-compatible JSDoc annotations on functions/classes/etc
* converts ES6 modules into goog.module modules
* generates externs.js from TypeScript d.ts (and declare, see below)
* declares types for class member variables
* translates export * from ... into a form Closure accepts
* converts TypeScript enums into a form Closure accepts
* reprocesses all jsdoc to strip Closure-invalid tags

Awesome! Unfortunately, tsickle isn’t exactly mainstream:

We already use tsickle within Google to minify our apps (including those using Angular), but we have less experience using tsickle with the various JavaScript builds that are seen outside of Google.

How can we use tsickle to transform typescript in our existing webpack (and/or) rollup based projects? The tsickle readme mentions that it’s a drop-in replacement for tsc, but does that mean we can use it directly with ts-loader? Luckily Inseok Lee has provided an example webpack loader as a github gist.

This loader is using the typescript compiler to load and process the tsconfig.json file, and then runs tsickle.emitWithTsickle to transform typescript. In our webpack config, we’ll replace ts-loader with this localtsickle-loader. This will produce an annotated javascript source:

You won’t actually see this annotated JS—the loader passes it through to the the rest of the webpack build process (e.g., the next loader in the chain).

This means that we can pass the tsickle-annotated javascript closure compiler in the webpack optimization stage:

Note that we use ModuleConcatenationPlugin; this is just to explicitly enable tree-shaking: closure compiler will perform advanced dead-code elimination, and if you output ES5 modules from it, webpack can reduce its bundling overhead via tree-shaking.

To use this setup in production, we wanted to add some tests to this loader and cover some edge cases in tsickle compilation:

  • handling multiple typescript module types (es5 output is optimal for tree-shaking)
  • allow passing options to specify the tsconfig.json and the location of the externs.js file
  • fix some issues in tsickle output (caused by using it in a webpack loader)

We’ve open sourced our implementation of tsickle-loader:


This is a webpack loader for tsickle; it lets us compile typescript code with the typescript compilaer, while adding annotations & externs readable by closure compiler, which means we can use ADVANCED_OPTIMIZATIONS mode. See the directory for an example of compiling this way.

Used with google-closure-compiler and the relatively newclosure-webpack-plugin, we can build some very optimized javascript. Given this arbitrary example:

closure-compiler outputs 1,333 bytes — the webpack terser default produces 1,466 bytes. These numbers aren’t that useful, since most of that output is the webpack bundler API. However you can see the closure-compiler output is able to mangle the class properties in a way that will help reduce bundle size as the code’s complexity grows.

Here’s the closure compiler output beautified so it’s easier to read:

Just 10kb of javascript reduced across 100 million SDK sessions will reduce bandwidth by 1TB. More importantly, it will help reduce resource usage across millions of phones and improve user experience.

You can see that tsickle+closure compiler correctly preserved the structure of the PublicAPI interface.

When you combine this with typescript’s module: "es2015" and use webpack’s tree-shaking (or, port the tsickle-loader to rollup), you can really reduce the impact of using utility libraries or 3rd-party code in your library—widely repeated imports are well-mangled, dead code is eliminated, and the remaining code is heavily optimized.

The closure compiler will also include any necessary polyfills based on your actual code usage and the target output language: es5 array methods are included individually, so you aren’t shipping a shim for findIndex if you only ever use find.

In some tests, we see smaller bundle sizes as the application gets larger:

Using Closure Compiler With Webpack + Typescript via Tsickle

Just 10kb of javascript reduced across 100 million SDK sessions will reduce bandwidth by 1TB. More importantly, it will help reduce resource usage across millions of phones and improve user experience.

Drive revenue and boost engagement. Find out how.

Read more
How to maximize Kinesis write throughput with Elixir

How to maximize Kinesis write throughput with Elixir


How to maximize Kinesis write throughput with Elixir


Written by Nico Piderman

How to maximize Kinesis write throughput with Elixir

At AppMonet we help mobile app developers maximize their advertising revenue by running auctions each time an ad slot is available on their users’ devices. This activity generates tons of data, almost all of which enters our system through AWS Kinesis.

We write billions of events to Kinesis each day, and if one isn’t careful, this kind of activity can end up costing a lot of money. The most efficient way to use the service is demonstrated by Amazon’s official Kinesis Producer Library (KPL). However, this library can only be used with Java. The features of this library that we are most interested in include:

Amazon also offers a series of aggregation libraries in several other popular languages which would allow you to aggregate your records using the same technique as the KPL, but leaves the actual transmission of the aggregated records to Kinesis up to the user. Sadly there is no official Elixir/Erlang aggregation library either.

However, the fine people over at AdRoll also make heavy use of Kinesis streams, and have published several open source libraries to help the BEAM community efficiently interact with Kinesis.

Erlmld and Exmld are two libraries made to help efficiently and safely consume Kinesis streams. Erlmld in particular, comes with a port of the Python implementation of the official Kinesis record aggregator. We extracted the producing logic and ported it to Elixir.

We have begun to use it internally because we didn’t want to pull in the entire Exmld package, which is for consuming streams, just to use this one aggregation module.


Once you start writing a non trivial amount of data to your first Kinesis stream, you will inevitably come across the “ProvisionedThroughputExceededException”. Don’t let this exception scare you in to scaling up your streams (and increasing your AWS bill) just yet!

Instead, your application should retry requests that produce this exception. The ExAws Elixir library comes with a great implementation of exponential backoff with jitter, and for many AWS services, this retry strategy will kick in automatically.

Unfortunately, we found that Kinesis Put Record API calls made with ExAwsKinesis do not trigger these automatic retries. We have patched the library and submitted our fix upstream and are waiting to hear back from the package maintainers.

For now, we are using our patched version with great success and enjoying excellent throughput on a minimal number of shards!

Practical Architecture

So what does this all look like in practice? There are three main pieces in our application.

  1. Poolboy pool
  2. GenServers
  3. Module to manage the GenServer state

We use a pool, mainly so no single GenServer becomes a bottle neck in our application.

You can adjust the size and max overflow of the pool according to your needs. We use the fifo strategy, so that we round robin through the pool and use all of the GenServers.

The GenServers look something like:

This GenServer provides an API function, write/1 which will check out a process from our pool, and push a new record to the GenServer’s state, which uses our KPL aggregator to pack it up and hold it until we are ready to send a batch to Kinesis.

The other important part to note here is the call to `Process.flag(:trap_exit, true)`, along with the implementation of the terminate/2 callback. These should ensure that any records that are being buffered in the GenServer state, are not lost when one of these GenServers is terminated.

Lastly, let’s take a look at the module that will manage the GenServer state:

This module is just a wrapper around the ExKpl aggregator. This module only exposes 3 will return a new aggregator. write/2 adds a new record to the aggregator, and will automatically flush once the aggregated record has reached the maximum size, and return a new aggregator. Finally flush/2 allows us to flush the aggregator and send all accumulated records to Kinesis. In some applications we also track the time of the last flush, so that we can have the aggregators flush if the elapsed time is greater than a certain threshold, but if your volume is high enough, you probably don’t need to worry about that.

This example uses the put_record API method, but you should also explore put_records as this method can send up to 500 records per request, each of which can be up to 1mb, so 5 of our carefully aggregated records a time.

Drive revenue and boost engagement. Find out how.

Read more