existence
← All posts
EngineeringAugust 2026 · 5 min read

Ads without the wiring: one advertising layer for every Existence app.

Banners, interstitials, rewarded video, native, and app-open ads now live behind a single tested package, one interface with the network swappable underneath, off until an app asks for it.

S
SiyabongaAuthor
XLinkedIn
Advertising

For most of our apps, showing an advertisement used to mean reaching for an SDK and wiring it in by hand. Ask for a banner here, load an interstitial there, remember to dispose of it, handle the load that quietly fails, repeat in the next app. It worked, but it was the same delicate plumbing rebuilt every time, and every app carried its own copy of the mistakes. This month we did what e_core is for: we built it once. e_core_ads is now live, and every app that adopts it gets the whole advertising stack behind a single import.

The trouble with bolting ads onto an app

Ads look simple from the outside: a strip at the bottom of the screen, a full-page promo between levels, a short clip you watch to earn something. Underneath, each format is its own small state machine. An ad has to be requested, and the request can succeed or fail. Once loaded it has to be shown, and once shown it has to be dismissed and cleaned up so it does not leak memory or money. A rewarded video has to tell you, reliably, whether the person actually earned their reward. Multiply those lifecycles across five ad formats and two platforms, and then multiply again across every app we ship, and a feature that sounds like one line of code becomes a surface area nobody wants to maintain twice.

That is exactly the tax e_core exists to remove. If more than one app needs it, it belongs in a package: built once, tested once, owned once, and used everywhere.

One interface, many networks

The heart of e_core_ads is a deliberately boring idea: an abstract AdsService that describes what an ads layer can do, with no opinion about who provides the ads. Initialise the service. Load and dispose a banner. Load and show an interstitial. Load and show a rewarded ad, and hand back the reward. Load and render a native ad that matches the app's own look. Show an app-open ad when someone returns. The apps only ever talk to that interface.

Behind it sits a concrete implementation built on Google's mobile ads platform, which is what actually serves the ads today. But because every app depends on the interface and never on the vendor, the vendor is a detail we can change. If we ever want to add a second network, run an experiment, or move a particular app to a different provider, that work happens in one place, behind a boundary the rest of the codebase never has to notice. The apps asked for "a rewarded ad," and they will keep getting one no matter what is wired in underneath.

The goal was never an ads library. It was to make where an ad comes from a decision we can change once, instead of a dependency baked into six apps.

Five formats, one lifecycle

The package ships every ad format our apps actually use, each behind the same predictable set of states so there is only one mental model to learn:

  • Banner: the persistent strip, loaded inline and disposed cleanly when the screen goes away.
  • Interstitial: the full-screen moment between natural breaks in a flow.
  • Rewarded: opt-in video that returns a verified reward through a callback, so the app knows exactly what was earned.
  • Native: an ad rendered in the app's own template, so it sits inside the design rather than on top of it.
  • App open: a brief placement shown when someone brings the app back to the foreground.

Every one of these moves through the same lifecycle, modelled as a small set of explicit states: loading, loaded, failed, shown, dismissed, and, for rewarded ads, rewarded. Because the states are named and typed rather than implied, a screen can react to each one on purpose, including the unglamorous case where an ad simply does not load and the layout has to carry on gracefully as if it were never there.

5ad formats, one interface
1place to swap the provider
Opt-inoff until an app asks

Off by default, and easy to turn off

An ads layer that ships inside shared infrastructure could easily become an ads layer that shows up everywhere whether you wanted it or not. We built the opposite. e_core_ads registers alongside the rest of the core services, but it stays dormant until an app opts in during setup, and it can be switched off again behind a single flag. That matters for us as builders, because an app that has no business showing ads never has to carry the weight of them, and it matters for the person using the app, because it keeps the decision about whether ads appear at all an explicit, reversible one rather than an accident of the framework.

Built once, inherited everywhere

Like the rest of e_core, this is not a snippet to copy between projects. It is a real package with a documented setup, worked examples for each format, and a test suite that exercises the full lifecycle of every ad type, including the failure paths, so the behaviour is pinned down rather than hoped for. An example app demonstrates all five formats end to end, which doubles as the place we manually sanity-check anything new before it reaches a real product.

The pattern is the same one we keep coming back to. Notifications, localisation, and now advertising were each a thicket of platform detail that every app used to solve on its own. Pulling them into shared, tested packages does not just save the writing; it means a single improvement lands everywhere at once, and the next app we build starts a little further ahead than the last. Monetisation is now just another capability an Existence app can switch on when it needs it, and leave alone when it does not.

S
SiyabongaWriting for Existence

Notes, as they happen.

One email when we publish. No digest, no drip, just the post.