Skip to main content
You run or verify ad campaigns and need to see which landing page a visitor in a given region on a given desktop reaches, and through which redirects. This walkthrough opens an ad link once per region and persona, prints every main-frame response on the way and saves a screenshot of the page it ends on. Opening a tracking link can register a click with the ad network. Check links from campaigns you run or are engaged to verify.

What Apostate changes

A persona is the platform a launch presents. It sets the operating system in the User-Agent, the Client Hints and navigator.platform, which ad servers and landing pages use to pick a creative or a download page. Personas are Windows, macOS and Linux desktops. Apostate has no mobile personas. A proxy gives the visit an IP address in the region. Before launch, the package sets the locale and timezone from the proxy’s exit, so the language and timezone agree with the IP address.

Set up

apostate fonts install windows is for Linux and macOS hosts (Fonts). verify_ads.py takes an ad or tracking link. For each region, it reads a proxy from APOSTATE_PROXY_US, APOSTATE_PROXY_DE or APOSTATE_PROXY_FR and skips a region whose variable is not set. With no link, it runs against a local ad server. The server redirects /click to /track, and /track to a landing page in the language of Accept-Language. The landing page’s script sends Mac visitors on to a /mac page.

The script

follow() opens the link with one persona and records each response to a main-frame navigation. That covers HTTP redirects and navigations a page’s script starts:
Each region’s launch options come from its proxy. In the local demo, a region is only its locale and timezone:

Run the demo

The first line of each block is the region, the persona, and the timezone and language the landing page read. The two 302 lines are the HTTP redirects. The tracker chose the landing page from Accept-Language. Under the macOS persona, the landing page’s script moved on to /mac, which shows as a second 200.

Run through regional proxies

Set a proxy for each region you want to check, then pass the link:
The script skips a region with no proxy. With no variable set, the output is:
Through a proxy, the package looks up the exit’s location before launch, so the timezone and language on each block’s first line are the ones it found. Check that they belong to the region. If the lookup fails, the package prints a warning that starts with apostate: , and the persona uses en-US and the host’s timezone. From 0.4.4 the warning is also in browser.apostate_diagnostics["warnings"]. Proxies covers the lookup.

Points for this job

  • Proxies. Use one exit per region, sticky for the length of a launch. Proxies covers sticky sessions.
  • Seeds. Each persona uses seed 42, so a rerun visits with the same two machines and a change in the result comes from the campaign. To see how a campaign treats other machines of one persona, add seeds.
  • What the chain records. The chain holds HTTP redirects and the navigations a page’s script starts, such as location.replace(). An ad inside an iframe navigates its own frame, so filter on that frame instead of page.main_frame. wait_for_load_state("networkidle") returns after 500 ms with no network connections. The chain misses a redirect that a page schedules later than that. To catch it, add page.wait_for_timeout() before the screenshot.
  • Headless. The screenshots are full-page captures from a headless launch, which presents the persona’s screen and window.