A rich-media expandable concept ad for the Tesla Model S, built the way the premium side of display advertising is delivered: a standalone HTML5 package that an ad server could traffic as is, running here inside a sandboxed iframe on a mock publisher page (Kerbside, a fictional motoring journal) that plays the role of the ad server's container.
Unofficial concept ad made for a portfolio, not affiliated with or endorsed by Tesla. Tesla is a trademark of Tesla, Inc. All figures (range, acceleration, top speed, charging, the range model) are illustrative. No official logo files or imagery: the T mark is a simple hand-drawn SVG and the car is drawn in code.
The package
- Lives in
public/lab/ads/expandable-ad/ with relative paths only, no frameworks and no external requests: index.html (the collapsed 300×250 teaser, styles inline), ad.js, expanded.css, expanded.js and backup.jpg. Weight per npm run ads (see manifest.json). index.html declares <meta name="ad.size" content="width=300,height=250"> and the expanded size, and defines var clickTag for the trafficker to override. Order now on the small unit is the default clickTag exit; Order now and Book a test drive in the panel are separate named exits, Order now carrying the chosen paint and wheels in its URL.- The teaser is CSS only: the car drives in with rolling wheels, the daytime lights wake up, a light sweeps over the body and three lines rotate (claim, range, acceleration). It plays three loops (about 20 s) and rests on its end frame, as display specs ask;
#backup hides the hover hint for the backup capture. - Polite load: only the collapsed frame loads up front. The expanded styles, the SVG scenes and the panel logic are injected after both the ad's own load event and the host page's load (the host says so in the handshake). Expanding before that queues the request until the panel arrives.
- The backup image is a 300×250 JPEG of the teaser's end frame, for environments where HTML5 cannot run; the inspector's Backup switch serves it in place of the frame.
The container API
ad.js exposes window.adkit, modelled on MRAID 2: expand(), close(), getState() (loading, default, expanded), addEventListener("stateChange"), plus exit(name, url) and track(name).- The creative never resizes itself. It posts
expand to the parent; the host page works out the placement, resizes the iframe and answers with a stateChange carrying the frame size and where the collapsed rectangle sits inside it. The creative then grows its panel from that rectangle. Closing runs the other way: the panel shrinks back first, then the creative posts collapse and the host shrinks the frame. - Messages are checked by source window (the sandbox gives the frame an opaque origin). Opened directly in a tab, the same package expands inside the window and exits use
window.open(clickTag); on this page the host asks it to post exits instead, so they show as a toast with the URL.
Expansion
- Desktop: a 970×500 overlay anchored to the slot's top-right corner, absolutely positioned so the article never moves (no pushdown). Phones, touch screens and windows too narrow for the panel get a full-screen interstitial that grows out of the slot, with the page under it locked and the example's floating back and menu buttons hidden until it closes.
- Mouse: half a second of hover intent before expanding, so brushing past does nothing. After a close with the pointer resting where the small unit comes back, hover re-arms only once the pointer has left (otherwise the ad would reopen at once). Touch: tap. Keyboard: Enter on the unit, and focus goes to the close button. Close with the × button or Esc (handled in the frame and on the page; Esc first dismisses an open hotspot card).
- The panel is a light, minimal showroom: brand row with an Exterior / Interior / Charging switch, the stage, and a side column with the model, three counted figures, a Design / Range estimator tab pair and the two exits.
- The car is inline SVG drawn in code: smooth fastback silhouette with no grille, paint gradient whose stops read CSS custom properties (so a swatch repaints it), horizon and shoulder reflections, sill, door lines, flush handles, repeater camera, charge-port door, mirror, one sweep of tinted glass from windscreen to tail with side windows and the cabin (headrests, steering wheel, ambient line) seen through them, slim LED headlight with an animated daytime light and beam, wraparound tail light with glow, soft ground shadow, and wheels with tyre sidewalls, drilled discs, calipers (red with the Sport wheels) and two rim designs (19″ Aero blades, 21″ Sport twin spokes) that crossfade.
- Hotspots (numbered, keyboard reachable): glass roof, headlights (replays the daytime light), wheels, charge port (opens the charging view); in the interior: touchscreen, glass roof and ambient lighting (cycles its colour).
- Charging view: the car steps aside for a charging post, current flows along the cable and a read-out counts 10 to 80% with power, added range and minutes on an illustrative curve.
- Range estimator: rated range by wheel, scaled by steady speed (80 to 140 km/h), outside temperature (−10 to 35 °C) and climate on or off. A deliberately simple illustrative model.
- The panel scale-in, the car's drive-in with rolling wheels, the daytime light, the studio light sweep and the content stagger are CSS transforms and opacity; the figures count up once.
Tracking
The host counts what an ad server report would: impressions (sent once the collapsed frame has painted), the polite load, expansions with their trigger (hover, tap, click, keyboard), interactions (paint, wheels, view, tab, hotspot, range), exits by name, collapses with their trigger, and total expansion time. The inspector bar shows the live container state and the counters; its log lists every event.
Reduced motion
The teaser shows its end frame, the panel opens and closes instantly, nothing drives in or sweeps, the figures and the charging read-out appear at their final values and the hover hint stops pulsing. The host also passes the setting to the frame, so it holds even when the frame cannot read the media query.
Honest limits
This is a demo container, not an ad server: no real MRAID SDK, no viewability measurement and no impression pixels. The ad is an unofficial concept with illustrative figures; Kerbside and the Ardent Lark are fictional.