From 4fde14394a7d69a2df7bd30bbff2788e2b940152 Mon Sep 17 00:00:00 2001 From: David Fischer Date: Tue, 26 Nov 2024 16:39:53 -0800 Subject: [PATCH] Link parameter substitutions - Link to documentation - Add substitutions for flight, country, and continent --- adserver/api/mixins.py | 3 +++ adserver/middleware.py | 10 +++++++- .../migrations/0099_link_advertiser_guide.py | 23 +++++++++++++++++++ adserver/models.py | 4 +++- adserver/utils.py | 1 + adserver/views.py | 5 ++++ 6 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 adserver/migrations/0099_link_advertiser_guide.py diff --git a/adserver/api/mixins.py b/adserver/api/mixins.py index 110345aa..bb2c0a70 100644 --- a/adserver/api/mixins.py +++ b/adserver/api/mixins.py @@ -57,5 +57,8 @@ def finalize_response(self, request, response, *args, **kwargs): response["X-Adserver-Country"] = str(request.geo.country) response["X-Adserver-Region"] = str(request.geo.region) response["X-Adserver-Metro"] = str(request.geo.metro) + response["X-Adserver-Continent"] = str(request.geo.continent) + response["X-Adserver-Latitude"] = str(request.geo.lat) + response["X-Adserver-Longitude"] = str(request.geo.lng) return response diff --git a/adserver/middleware.py b/adserver/middleware.py index e3fe3aab..4b31802f 100644 --- a/adserver/middleware.py +++ b/adserver/middleware.py @@ -180,9 +180,12 @@ class CloudflareGeoIpMiddleware(GeoIpMiddleware): COUNTRY_HEADER = "CF-IPCountry" # These fields will require a custom transform rule - # https://developers.cloudflare.com/rules/transform/ + # https://developers.cloudflare.com/rules/transform/managed-transforms/reference/#add-visitor-location-headers REGION_HEADER = "X-Cloudflare-Geo-Region" # ip.src.region_code METRO_HEADER = "X-Cloudflare-Geo-Metro" # ip.src.metro_code + CONTINENT_HEADER = "X-Cloudflare-Geo-Continent" # ip.src.continent + LATITUDE_HEADER = "X-Cloudflare-Geo-Lat" # ip.src.lat + LONGITUDE_HEADER = "X-Cloudflare-Geo-Lon" # ip.src.lon def get_geoip(self, request): geo = super().get_geoip(request) @@ -194,8 +197,13 @@ def get_geoip(self, request): country_code = None geo.country = country_code + # Region is the state/province within a country (not wider region like EU) + # See "continent" geo.region = request.headers.get(self.REGION_HEADER, None) geo.metro = request.headers.get(self.METRO_HEADER, None) + geo.continent = request.headers.get(self.CONTINENT_HEADER, None) + geo.lat = request.headers.get(self.LATITUDE_HEADER, None) + geo.lng = request.headers.get(self.LONGITUDE_HEADER, None) return geo diff --git a/adserver/migrations/0099_link_advertiser_guide.py b/adserver/migrations/0099_link_advertiser_guide.py new file mode 100644 index 00000000..632604d7 --- /dev/null +++ b/adserver/migrations/0099_link_advertiser_guide.py @@ -0,0 +1,23 @@ +# Generated by Django 5.0.9 on 2024-11-27 00:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('adserver', '0098_rotation_aggregation'), + ] + + operations = [ + migrations.AlterField( + model_name='advertisement', + name='link', + field=models.URLField(help_text="URL of your landing page. This may contain UTM parameters so you know the traffic came from us. The publisher will be added in the 'ea-publisher' query parameter. Additional variable substitutions are available. See the advertiser guide. ", max_length=1024, verbose_name='Link URL'), + ), + migrations.AlterField( + model_name='historicaladvertisement', + name='link', + field=models.URLField(help_text="URL of your landing page. This may contain UTM parameters so you know the traffic came from us. The publisher will be added in the 'ea-publisher' query parameter. Additional variable substitutions are available. See the advertiser guide. ", max_length=1024, verbose_name='Link URL'), + ), + ] diff --git a/adserver/models.py b/adserver/models.py index 714fb145..fe69f013 100644 --- a/adserver/models.py +++ b/adserver/models.py @@ -1613,7 +1613,9 @@ class Advertisement(TimeStampedModel, IndestructibleModel): help_text=_( "URL of your landing page. " "This may contain UTM parameters so you know the traffic came from us. " - "The publisher will be added in the 'ea-publisher' query parameter." + "The publisher will be added in the 'ea-publisher' query parameter. " + "Additional variable substitutions are available. " + "See the advertiser guide. " ), ) image = models.ImageField( diff --git a/adserver/utils.py b/adserver/utils.py index 1c7e2d61..15068b7c 100644 --- a/adserver/utils.py +++ b/adserver/utils.py @@ -53,6 +53,7 @@ class GeolocationData: metro: int = None lat: float = None lng: float = None + continent: str = None def get_ad_day(): diff --git a/adserver/views.py b/adserver/views.py index 3d849eaa..bef9bc84 100644 --- a/adserver/views.py +++ b/adserver/views.py @@ -1207,6 +1207,11 @@ def get_response(self, request, advertisement, publisher): advertisement=advertisement.slug, advertisement_slug=advertisement.slug, advertisement_name=advertisement.name, + flight=advertisement.flight.slug, + # For privacy, don't reveal more than country/continent to advertisers + country=str(request.geo.country) if request.geo else "None", + # request.geo.region is a state/province/region inside a country + continent=str(request.geo.continent) if request.geo else "None", ) # Append a query string param ?ea-publisher=${publisher}