Skip to content

Commit ee783d1

Browse files
author
Sam Kleinman
committed
DOCS-201 inital structural edit pass
1 parent 02be2ab commit ee783d1

File tree

5 files changed

+132
-92
lines changed

5 files changed

+132
-92
lines changed

draft/index.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ Signposts
6363
:maxdepth: 2
6464

6565
sharding
66-
use-cases
6766

6867
Reference
6968
~~~~~~~~~

draft/use-cases/ad-campaign-management.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ Query
137137
138138
TODO: describe query
139139
140-
Index Support
141-
`````````````
140+
Indexing
141+
````````
142142
143143
TODO: describe indexes to optimize this query
144144

draft/use-cases/ad-serving-ads.txt

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
.. -*- rst -*-
2-
31
==============================
42
Online Advertising: Ad Serving
53
==============================
@@ -35,15 +33,17 @@ The examples that follow use the Python programming language and the
3533
:api:`PyMongo <python/current>` :term:`driver` for MongoDB, but you
3634
can implement this system using any language you choose.
3735

38-
Design 1: Basic Ad Serving
39-
--------------------------
36+
Serving Basic Ads
37+
-----------------
4038

41-
A basic ad serving algorithm consists of the following steps:
39+
A basic ad serving algorithm consists of the following The:
4240

43-
#. The network receives a request for an ad, specifying at a minimum the
41+
#. steps network receives a request for an ad, specifying at a minimum the
4442
``site_id`` and ``zone_id`` to be served.
43+
4544
#. The network consults its inventory of ads available to display and chooses an
4645
ad based on various business rules.
46+
4747
#. The network returns the actual ad to be displayed, possibly recording the
4848
decision made as well.
4949

@@ -52,8 +52,8 @@ as well as information stored in the ad inventory collection, to make the ad
5252
targeting decisions. Later examples will build on this, allowing more advanced ad
5353
targeting.
5454

55-
Schema Design
56-
~~~~~~~~~~~~~
55+
Schema
56+
~~~~~~
5757

5858
A very basic schema for storing ads available to be served consists of a single
5959
collection, ``ad.zone``:
@@ -83,6 +83,9 @@ ads, sorted by their ``ecpm`` values.
8383
Choosing an Ad to Serve
8484
~~~~~~~~~~~~~~~~~~~~~~~
8585

86+
Querying
87+
````````
88+
8689
The query you'll use to choose which ad to serve selects a compatible ad and
8790
sorts by the advertiser's ``ecpm`` bid in order to maximize the ad network's
8891
profits:
@@ -101,8 +104,8 @@ profits:
101104
ecpm, ad_group = ecpm_groups.next()
102105
return choice(list(ad_group))
103106

104-
Index Support
105-
`````````````
107+
Indexing
108+
````````
106109

107110
In order to execute the ad choice with the lowest latency possible, you'll want
108111
to have a compound index on (``site_id``, ``zone_id``):
@@ -116,6 +119,9 @@ to have a compound index on (``site_id``, ``zone_id``):
116119
Making an Ad Campaign Inactive
117120
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118121

122+
Updating
123+
````````
124+
119125
One case you'll have to deal with in this solution making a campaign
120126
inactive. This may happen for a variety of reasons. For instance, the campaign
121127
may have reached its end date or exhausted its budget for the current time
@@ -133,8 +139,8 @@ The update statement above first selects only those ad zones which had avaialabl
133139
ads from the given ``campaign_id`` and then uses the ``$pull`` modifier to remove
134140
them from rotation.
135141

136-
Index Support
137-
`````````````
142+
Indexing
143+
````````
138144

139145
In order to execute the multi-update quickly, you should maintain an index on the
140146
``ads.campaign_id`` field:
@@ -158,8 +164,8 @@ good approach is to shard on the (``site_id``, ``zone_id``) combination:
158164
... 'key': {'site_id': 1, 'zone_id': 1} })
159165
{ "collectionsharded": "ad.zone", "ok": 1 }
160166

161-
Design 2: Adding Frequency Capping
162-
----------------------------------
167+
Adding Frequency Capping
168+
------------------------
163169

164170
One problem with the logic described in Design 1 above is that it will tend to
165171
display the same ad over and over again until the campaign's budget is
@@ -174,8 +180,8 @@ transmitted to the ad network when logging impressions, clicks, conversions,
174180
etc., as well as the ad serving decision. This section focuses on how that
175181
profile data impacts the ad serving decision.
176182

177-
Schema Design
178-
~~~~~~~~~~~~~
183+
Schema
184+
~~~~~~
179185

180186
In order to use the user profile data, you need to store it. In this case, it's
181187
stored in a collection ``ad.user``:
@@ -210,17 +216,22 @@ There are a few things to note about the user profile:
210216
- Profile information is segmented by advertiser. Typically advertising data is
211217
sensitive competitive infomration that can't be shared among advertisers, so
212218
this must be kept separate.
219+
213220
- All data is embedded in a single profile document. When you need to query this
214221
data (detailed below), you don't necessarily know which advertiser's ads you'll
215222
be showing, so it's a good practice to embed all advertisers in a single
216223
document.
224+
217225
- The event information is grouped by event type within an advertiser, and sorted
218226
by timestamp. This allows rapid lookups of a stream of a particular type of
219227
event.
220228

221229
Choosing an Ad to Serve
222230
~~~~~~~~~~~~~~~~~~~~~~~
223231

232+
Querying
233+
````````
234+
224235
The query you'll use to choose which ad to serve now needs to iterate through
225236
ads in order of desireability and select the "best" ad that also satisfies the
226237
advertiser's targeting rules (in this case, the frequency cap):
@@ -275,8 +286,8 @@ stored in the user profile, from most recent to oldest, within a certain
275286
appears in the mipression stream, the ad is rejected. Otherwise it is acceptable
276287
and can be shown to the user.
277288

278-
Index Support
279-
`````````````
289+
Indexing
290+
````````
280291

281292
In order to retrieve the user profile with the lowest latency possible, there
282293
needs to be an index on the ``_id`` field, which MongoDB supplies by default.
@@ -293,8 +304,8 @@ When sharding the ``ad.user`` collection, choosing the ``_id`` field as a
293304
... 'key': {'_id': 1 } })
294305
{ "collectionsharded": "ad.user", "ok": 1 }
295306

296-
Design 3: Keyword Targeting
297-
---------------------------
307+
Keyword Targeting
308+
-----------------
298309

299310
Where frequency capping above is an example of user profile targeting, you may
300311
also wish to perform content targeting so that the user receives relevant ads for
@@ -303,9 +314,8 @@ at the result of a search query. In this case, a list of ``keywords`` is sent to
303314
the ``choose_ad()`` call along with the ``site_id``, ``zone_id``, and
304315
``user_id``.
305316

306-
307-
Schema Design
308-
~~~~~~~~~~~~~
317+
Schema
318+
~~~~~~
309319

310320
In order to choose relevant ads, you'll need to expand the ``ad.zone`` collection
311321
to store keywords for each ad:

0 commit comments

Comments
 (0)