Ad Config

In order to make the API fetch request more cacheable, in granular chunks, Ad Config was removed from the Drupal response and handled in a second request.

After a fetch request, eg:

/{DrupalApiPath}/api/{publicationDomain}?path={entityPath}

The setAdConfig service is piped into the response before the fetch request resolves.

where the Drupal API response contains an adConfig param, the service requests the Ad config with fetchAdConfig (see: /src/api/fetch)

The response from fetchAdConfig is then added to the fetch response overriding the Ad Config Id:

{
  "adConfig": {
    "desktop": {
      "top_banner": true,
      "article_body": true,
      "paragraph_freq": 4,
      "paragraph_size": "",
      "liveblog_post": true,
      "liveblog_post_freq": 4,
      "sidebar": true,
      "video": true,
      "native": true,
      "native_section": true,
      "teads": true,
      "wallpaper": true,
      "seedtag": true,
      "ad_slot": true,
      "ad_row_billboard": true,
      "on_scroll": true,
      "outbrain_feed": true,
      "outbrain_mid": true
    },
    "desktopAdlite": {
      "article_body": true,
      "paragraph_freq": 7,
      "paragraph_size": 1,
      "liveblog_post": true,
      "liveblog_post_freq": 7,
      "liveblog_post_size": 1,
      "sidebar": true,
      "native": true,
      "native_section": true
    },
    "mobile": {
      "top_banner": true,
      "article_body": true,
      "paragraph_freq": 4,
      "liveblog_post": true,
      "liveblog_post_freq": 4,
      "bottom_banner": true,
      "native": true,
      "native_section": true,
      "teads": true,
      "wallpaper": true,
      "seedtag": true,
      "ad_slot": true,
      "ad_row_billboard": true,
      "taboola_feed": true,
      "taboola_mid": true,
      "outbrain_feed": true,
      "outbrain_mid": true
    },
    "mobileAdlite": {
      "top_banner": false,
      "article_body": true,
      "paragraph_freq": 7,
      "paragraph_size": 1,
      "liveblog_post": true,
      "liveblog_post_freq": 7,
      "liveblog_post_size": 1,
      "native": true,
      "native_section": true,
      "outbrain_feed": false,
      "outbrain_mid": false
    },
    "amp": {
      "outbrain_feed": true,
      "outbrain_mid": true,
      "top_banner": true,
      "article_body": true,
      "paragraph_freq": 4,
      "mpu_1_multisize": true,
      "video": true,
      "bottom_banner": true,
      "native": true,
      "teads": true
    }
  }
}

Depricated Ad Config

The Indy and ES still use the deprecated ad config, this will display in the following format:

{
  "adConfig": [
    {
      "type": "TopBanner",
      "label": "Top Banner",
      "id": "t5lrnwlw",
      "value": true
    },
    {
      "type": "WallPaper",
      "label": "Wallpaper",
      "id": "35wxxbyo",
      "value": true
    },
    {
      "type": "Teads",
      "label": "Teads",
      "id": "ootdhzxg",
      "value": true
    },
    {
      "type": "ArticleBody",
      "label": "Article Body",
      "id": "bv6xfam0",
      "value": true,
      "frequency": 4
    },
    {
      "type": "LiveblogPost",
      "label": "Liveblog Post",
      "id": "bcqverjg",
      "value": true
    },
    {
      "type": "RightHandSide",
      "label": "Right Hand Side",
      "id": "a6n7lf2l",
      "value": true
    },
    {
      "type": "BottomBanner",
      "label": "Bottom Banner",
      "id": "7lf73sqb",
      "value": true
    },
    {
      "type": "Native",
      "label": "Native",
      "id": "auq6dklb",
      "value": true
    },
    {
      "type": "VideoRoll",
      "label": "Video Pre roll, Mid roll & Post roll",
      "id": "pmf130z7",
      "value": true
    },
    {
      "type": "Taboola",
      "label": "Taboola",
      "id": "47nonvdu",
      "value": true
    },
    {
      "type": "OnScroll",
      "label": "On Scroll right hand rail",
      "id": "3mnzc5g3",
      "value": true
    },
    {
      "type": "AdSlot3X3",
      "label": "Ad Slot 3x3",
      "id": "gtmjcn11",
      "value": true
    },
    {
      "type": "AdSlot2X3",
      "label": "Ad Slot 2x3",
      "id": "7vqz09b0"
    },
    {
      "type": "LiteTopBanner",
      "label": "Top Banner",
      "id": "e73hajhg",
      "value": true
    },
    {
      "type": "LiteWallPaper",
      "label": "Wallpaper",
      "id": "e0xgk324",
      "value": true
    },
    {
      "type": "LiteTeads",
      "label": "Teads",
      "id": "94i0fmsv",
      "value": true
    },
    {
      "type": "LiteArticleBody",
      "label": "Article Body",
      "id": "1rhb11j0",
      "value": true,
      "frequency": 4
    },
    {
      "type": "LiteLiveblogPost",
      "label": "Liveblog Post",
      "id": "hvtsqork",
      "value": true
    },
    {
      "type": "LiteRightHandSide",
      "label": "Right Hand Side",
      "id": "10pmr5kx",
      "value": true
    },
    {
      "type": "LiteBottomBanner",
      "label": "Bottom Banner",
      "id": "4svzdwu8",
      "value": true
    },
    {
      "type": "LiteNative",
      "label": "Native",
      "id": "93yza9a8",
      "value": true
    },
    {
      "type": "LiteVideoRoll",
      "label": "Video Pre roll, Mid roll & Post roll",
      "id": "ez11py8l",
      "value": true
    },
    {
      "type": "LiteTaboola",
      "label": "Taboola",
      "id": "qlo8ryv2",
      "value": true
    },
    {
      "type": "LiteOnScroll",
      "label": "On Scroll right hand rail",
      "id": "65huypyy",
      "value": true
    },
    {
      "type": "LiteAdSlot3X3",
      "label": "Ad Slot 3x3",
      "id": "26spat08",
      "value": true
    },
    {
      "type": "LiteAdSlot2X3",
      "label": "Ad Slot 2x3",
      "id": "w2k2z2gt"
    }
  ]
}

JPI Frontend Implementation

The JPI Frontend logic mostly makes use of the following function found in /app/services/ads.js

/**
 * Gets first setting found from a group of configs
 * @param adConfig
 * @param setting
 * @param group
 * @return {boolean|*}
 */
export const getAdConfigSetting = (adConfig, setting, group) => {
  const groups = Array.isArray(group) ? group : [group];
  for (let i = 0; i <= groups.length; i += 1) {
    if (adConfig?.[groups[i]]?.[setting]) {
      return adConfig[groups[i]][setting];
    }
  }
  return false;
}

This logic is simple, if a specific setting (this maps to the tile string from the config above) exists within a group (the ad config tab) and is truthy this part may be incorrect as 0 could still be a valid option return it's value.

This is used predominantly in the 2 Article type body content templates to inject Ads into the array of components before rendering:

if (cleanAmp && getAdConfigSetting(adConfig, ADSLOT_TEADS, ADCONFIG_AMP)) {
  componentWithAds.push({
    type: 'markupAds',
    data: {
      width: 300,
      height: 1,
      id: GPT_TEADSIB,
      ...ampAdData(slotParams(GPT_TEADSIB)),
      'data-enable-refresh': 'false',
      cleanAmp,
    },
    cleanAmp,
  });
}

in this example the groups is a single string constant ADCONFIG_AMP, so the function will check for the existance of the ADSLOT_TEADS param in the ADCONFIG_AMP tab only.