The spec
field within each channel describes the campaign it's associated with.
campaignSpec
refers to the format of describing ad campaigns.
If a channel is associated with a campaign (in practice, all channels created by the AdEx dapp are), it's on-chain spec
field would be set to a sha256 hash of the JSON blob of the channel.spec
field.
Within the validator stack, the spec
is submitted as part of the POST /channel
request.
Because the campaignSpec
format needs to be able to evolve rapidly, we can use a wrapper that also contains the format version.
Please note, this wrapper format is not in use as of Q1 2019 (v4.0). If we decide to use it later, we can obsolete the channel.spec
field and introduce another field which contains this wrapper.
version
: a semver version of the formatbody
: thecampaignSpec
body
Example: { "version": "1.0.0-beta", "body": "..." }
NOTE: all monetary values are represented as a string that represents a decimal BigNumber in the channel asset unit (BigNumString)
title
: string, used mostly for advertisers own infovalidators
: an array of Validator objects; should always be 2 elements, first being the leader, second being the followerpricingBounds
: a map ofevType
->Bounds
, whereBounds
is an object that hasmin
/max
, both of them BigNumStr; defines the min/max prices for events; e.g.{ CLICK: { min: "0", max: "1000" } }
maxPerImpression
: BigNumStr, a maximum payment per impression; OBSOLETE, only used ifpricingBounds
is missing anIMPRESSION
entryminPerImpression
: BigNumStr, minimum payment offered per impression; OBSOLETE, only used ifpricingBounds
is missing anIMPRESSION
entrytargeting
: obsoleteminTargetingScore
: obsoletetargetingRules
: array of targeting DSL rules; see Targeting and bidding for more detailseventSubmission
: EventSubmission object, applies to event submission (POST/channel/:id/events
)created
: Number, a millisecond timestamp of when the campaign was createdactiveFrom
: optional, Number, a millisecond timestamp representing the time you want this campaign to become active; used by theAdViewManager
nonce
: BigNumStr, a random number to ensure the campaignSpec hash is uniquewithdrawPeriodStart
: Number, a millisecond timestamp of when the campaign should enter a withdraw period (no longer accept any events other thanCHANNEL_CLOSE
); a sane value should be lower thanchannel.validUntil * 1000
and higher thancreated
; it is strongly recommended to set this at least one month prior tochannel.validUntil * 1000
, to allow enough time for earnings to be claimed by everyoneadUnits
: optional, an array of AdUnitdepositChainId
: optional, the id of the chain of thedepositAsset
; if it's not passed, it will try to infer it from thedepositAsset
token address.
id
: string, the corresponding value inchannel.spec.validators
url
: string, a HTTPS URL to the validator's sentryfee
: BigNumStr, the total fee that will be paid out to this validator when they distribute the whole remaining channel depositfeeAddr
: string, an address where the fee would be received; optional - if it's not provided,id
will be used
Rules that apply to submitting events
allow
: array ofEventSubmissionRule
; for each POST to/channel/:id/events
, the first rule that matches will apply
NOTE: submission rules (limits) apply to channels as a whole, rather than individual ad units. This means that, a single campaign will only be counted once per the rateLimit
window, no matter how many ad units are shown to the user
uids
: array of user IDs that this rule applies to; leavenull
for applying to everyone (note that subsequent rules inallow
won't match); set to[null]
to apply to requests without authenticationevTypes
: array of event types that this rule applies to; leavenull
for applying to all eventsrateLimit
: optional, object describing the rate limit to apply; for, this takes{ type, timeframe }
, wheretimeframe
is a number of milliseconds;type
can be"ip"
or"uid"
- the
"ip"
type limits by the user's IP - the
"uid"
type limits by the user ID; it won't allow any event submissions if the request is not authenticated - TODO:
"pow"
type, AIP26 - TODO:
"captcha"
type, AIP29, together with{ evTypes: ["CLICK"] }
- the
If a rate limit applies, only one event can be submitted with one request.
To enable the creator to submit as many events as they like (and submit multiple at once), add a rule that matches them that has no rateLimit
: { uids: [channel.creator] }
.
{ allow: [{ uids: null, rateLimit: { type: "ip", timeframe: 1000 } }] }
- this will allow everyone to submit events, at a rate of 1 event per second per IP
{ allow: [{ uids: null }] }
- this will allow everyone to submit events with no limit
{ allow: [{ uids: null, rateLimit: { type: "ip", timeframe: 1000 } }, { uids: null, rateLimit: { type: "uid", timeframe: 1000 } }] }
- will apply both an IP limit and a UID limit
{ allow: [{ uids: [channel.creator] }, { uids: null, rateLimit: { type: "ip", timeframe: 1000 } }] }
- this will allow the creator to submit as many events as they like, but everyone else will be restricted to 1 event per second per IP
Spec properties (added to ipfs and can NOT be modified)
ipfs
: string, valid ipfs hash of spec props belowtype
: string, the type of the ad unit; currently, possible values are:legacy_300x250
,legacy_250x250
,legacy_240x400
,legacy_336x280
,legacy_180x150
,legacy_300x100
,legacy_720x300
,legacy_468x60
,legacy_234x60
,legacy_88x31
,legacy_120x90
,legacy_120x60
,legacy_120x240
,legacy_125x125
,legacy_728x90
,legacy_160x600
,legacy_120x600
,legacy_300x600
, see IAB ad unit guidelines andiab_flex_{adUnitName}
(see IAB's new ad portfolio and PDF)mediaUrl
: string, a URL to the resource (usually PNG); must use theipfs://
protocol, to guarantee data immutabilitymediaMime
: string, MIME type of the media, possible values at the moment are:image/jpeg
,image/png
targetUrl
: string, the advertised URLtargeting
: obsoletetags
: obsoletecategories
: categories of that ad unit, based on thetargetUrl
and the media; array of strings, following the IAB taxonomyowner
: user address from the sessioncreated
: number, UTC timestamp in milliseconds, used as nonce for escaping duplicated spec ipfs hashes
title
: string, the name of the unit used in platform UIdescription
: string, arbitrary text used in platform UIarchived
: boolean, user can change it - used for filtering in platform UImodified
: number, UTC timestamp in milliseconds, changed every time modifiable property is changed