placement.js arguments

This article describes the arguments passed to your renderPlacement function.

meta

module.exports = function renderPlacement ({ meta }) {
  console.log(meta)
}

The meta object contains information about the currently executing Placement and its context:

Attribute Description

cookieDomain

The domain value that cookies have been configured to be stored against. This is useful if you need to store cookies in a consistent way.

isPreview

Whether the variant is executing in preview mode (can be useful if you want to avoid sending data while previewing, for example).

trackingId

The tracking ID of the property on which the experience is executing.

namespace

The value of your configured namespace if you have one. This allows you to define a custom schema.

vertical

A code representing your industry sector. This affects what events you should send and their prefix.

placementId

The ID of the currently executing Placement.

visitorId

The visitor ID.

elements

module.exports = function renderPlacement ({ elements }) {
  console.log(elements)
}

The elements array contains the results of evaluating all the Polling for simple triggers.

onImpression

module.exports = function renderPlacement ({ onImpression }) {
  onImpression()
}

You should call the onImpression function whenever your Placement might have been seen by an eligible visitor. When a campaign is live that targets your Placement, this will allow us to report on who saw it and what impact it may have had on them.

It’s important to call onImpression both when there’s content and when there isn’t so that the reporting can compare visitors who saw the campaign with those that didn’t.

The criteria used to decide whether to call onImpression should be equivalent regardless of whether there’s content or not. This equivalence helps avoid introducing bias when performing A/B tests on campaigns.

Note

See our guide on impressions and clickthroughs for more details.

onClickthrough

module.exports = function renderPlacement ({ onClickthrough }) {
  onClickthrough()
}

You should call the onClickthrough function whenever your Placement gets clicked or interacted with. When a campaign is live that targets your Placement, this will allow us to report on visitor engagement with your campaign.

If your Placement is replacing an element such as a carousel, it’s important to set up click handlers that call onClickthrough both for the original element you’re replacing and for the one you’re replacing it with. This approach will allow the reporting to compare the engagement of visitors who saw the campaign with those that did not.

See our guide on impressions and clickthroughs for more details.

log

module.exports = function renderPlacement (options) {
  console.log(options.log)
}

A stylish logger, useful for development of Placements. See https://github.com/QubitProducts/driftwood for more info:

module.exports = function renderPlacement ({ log }) {
  try {
    log.info('hello from variation ' + options.variationMasterId)
    throw new Error('stone')
  } catch (eek) {
    log.error('', eek)
  }
}

getVisitorState

module.exports = function renderPlacement ({ getVisitorState }) {
  getVisitorState().then(function (state) {
    console.log(state)
  })
}

This method allows you to get useful information about a user, including an IP address.

The getVisitorState method returns a sync-p style promise usually resolved synchronously, but on the first view of a session, syncing with the lookup API will cause it to be asynchronous. Cross-domain setups will always have an asynchronous getVisitorState method. However, this setup is rare.

state :

Attribute Description

viewTs

A timestamp for the most recent view event

pageViewNumber

The number of views the visitor has had

cookiePersists

False if the user’s cookie fails to persist

timezoneOffset

The timezone offset of the visitor in minutes from UTC

visitorId

Equivalent of context Id and cookie Id that’s randomly assigned to each visitor to identify them on your site - device specific

conversionNumber

The number of conversions the visitor has made - updated on the next view event after a conversion

conversionCycleNumber

The number of conversion cycles the visitor has had across their lifetime.The conversionCycleNumber increments only on the session following a session with one or more conversions

lifetimeValue

The total amount transacted by the visitor over their lifetime - updated at the beginning of the next session

firstViewTs

The date of the first View for the visitor

lastViewTs

The date of the last View for the visitor

viewNumber

The number of view event across the user’s lifetime

entranceViewNumber

The number of views the visitor has seen in the entrance

sessionNumber

The number of sessions the visitor has had across their lifetime

entranceNumber

The number of entrances the visitor has had across their lifetime

ipAddress

The IP Address of the device

entranceTs

Timestamp for when the entrance was initiated

sessionViewNumber

The number of views the visitor has seen in the session

eventNumber

The sequence number of the event for the current page view

sessionTs

Timestamp for when the session was initiated

sample

A number between 0 and 99 999 based on a hash of the visitor Id

city

The city name

cityCode

The city code

country

The country name

countryCode

The ISO 4217 currency code for the user (for example, GBP, USD)

latitude

The latitude value

longitude

The longitude value

area

The area name

areaCode

The area code

region

The region name

regionCode

The region code

Tip
Leading practice

A typical use case for getting a user’s IP address is to exclude a range of IP addresses from Qubit tests.

getBrowserState

module.exports = function renderPlacement (options) {
  options.getBrowserState().then(function (state) {
    console.log(state)
  })
}

Returns useful information about the user’s browser.

The getBrowserState method returns a sync-p style promise that always resolves synchronously.

state :

Attribute Description

url

The current URL

host

The current host

referrerUrl

The referrer URL

doNotTrack

Whether the user has expressed a preference not to be tracked by web sites

ua.deviceType

The users' device type

ua.deviceName

The users' device name

ua.osName

The users' OS name

ua.osVersion

The users' OS version

ua.browserName

The users' Browser name

ua.browserVersion

The users' Browser version

ua.userAgent

The users' User Agent string

isBot

Whether the user is a bot

time

A timestamp for when the users' browser state was computed

screenWidth

The users screen width

screenHeight

The users screen height

poll

Poll allows you to wait for:

  • The presence of DOM elements

  • The presence of window variables

  • Arbitrary conditions

and returns a promise for those elements, variables or the results of your custom poll functions:

// Wait for the presence of DOM elements by passing in a selector:
options.poll('body > .nav').then(function (nav) {
  console.log(nav)
})

// Wait for window variables to be defined:
options.poll('window.foo.bar').then(function (bar) {
  console.log(bar)
})

// Wait for arbitrary conditions to become truthy by passing in a custom function:
options.poll(() => true).then(result => console.log(result))

// Mix and match:
options.poll(['body > .nav', 'window.foo', () => 1234]).then(function ([nav, foo, id]) {
  console.log(nav, foo, id)
})

// Create a poller instance with several targets
const poller = options.poll([
  'body > .nav',
  'window.foo.bar',
  () => true
])

// Start polling
poller
  // returns a promise for the items being polled for
  .then(function ([nav, bar, truthy]) {
    console.log(nav, bar, truthy)
  })

// Stop polling
poller.stop()

// Start polling again
poller.start()

This uses @qubit/poller under the hood but is configured to provide useful logging when in preview mode.

uv

Our UV API is accessible as an argument and enables developers to build Placements that take advantage of our event-based protocol.

on

uv.on(type, handler, [context])

Attaches an event handler to be called when a certain event type is emitted. The handler will be passed the event data and will be bound to the context object if one is passed. If a regex is passed, the handler will execute on events that match the regex:

uv.on('ecProduct', function (data) {
  console.log(data)
})
// => logs data when an `ecProduct` event is emitted

var subscription = uv.on(/.*/, function (data) {
  console.log(data)
})
// => logs data for all events

The on method returns a subscription object that can detach the handler using the dispose method and can also be used to replay events currently in the event array:

subscription.dispose()
// => detaches the event handler

subscription.replay()
// => calls the handler for all events currently in uv.events
Note

Subscriptions that have been disposed of won’t call the handler when replay is called.

Note

On Single Page Applications that emit multiple view events per page, replay() only replays events since the latest view, including the latest view event. This makes accessing data layer information about the current page easier.

once

uv.once(type, handler, [context])

Attaches an event handler that will be called once, only on the next event emitted that matches the type specified. The handler will be passed the event data and will be bound to the context object if one is passed. Returns a subscription object which can detach the handler using the dispose method. If a regex is passed, the handler will execute on the next event to match the regex:

uv.once('ecProduct', function (data) {
  console.log(data)
})
emit('ecProduct')
// => logs data

emit('ecProduct')
// => does not log

The once method returns a subscription object, which can detach the handler using the dispose method, and can also be used to replay events currently in the event array:

subscription.dispose()
// => detaches the event handler

subscription.replay()
// => calls the handler for all events currently in uv.events
Note

Subscriptions that have been disposed of will not call the handler when replay is called.

Note

On single-page applications that emit multiple view events per page, replay() only replays events since the latest view, including the latest view event. This makes accessing data layer information about the current page easier.

emit

uv.emit(type, [data])

Emits an event with the type and data specified. The data should conform to the schema for the event type emitted. All events that are emitted are given a meta property with the event type:

uv.emit('ecProduct', {
  product: {
    id: '112-334-a',
    price: 6.99,
    name: '18th Birthday Balloon',
    category: ['Party Accessories', 'Birthday Parties']
  },
  color: 'red',
  stock: 6,
  eventType: 'detail'
})
// => emits an ecProduct event

The emitted event will have metadata attached:

{
  "meta": {
    "type": "ecProduct"
  },
  "product": {
    "id": "112-334-a",
    "price": 6.99,
    "name": "18th Birthday Balloon",
    "category": ["Party Accessories", "Birthday Parties"]
  },
  "color": "red",
  "stock": 6,
  "eventType": "detail"
}

Events

The events array is a cache of events emitted since the last page load. By iterating over the array, it is possible to interpret the visitor journey or the current state of the page.

onRemove

This hook lets you register any cleanup functions such as removing event listeners, which will be called if Smartserve restarts. This is particularly important in a single page application (SPA), as it allows you to prevent side effects carrying over between virtual page views.

If you implement this method, you will also be able to use the hot reloading feature of Coveo Qubit CLI.

module.exports = function renderPlacement ({ onRemove }) {
  onRemove(cleanup)
  return true
}