npm package: @smg-automotive/advertisement-pkg
Description: Contains Relevant Digital Header Bidding Wrapper for advertisements
Author: SMG Automotive
Latest version: 2.4.0

# advertisement-pkg

Contains Relevant Digital Header Bidding Wrapper for advertisements.

[![CircleCI](https://dl.circleci.com/status-badge/img/gh/smg-automotive/advertisement-pkg/tree/main.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/smg-automotive/advertisement-pkg/tree/main)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)

## About

This library is created in an effort to integrate Relevant Digital HB Wrapper. It supports both Microsoft ASN and Google GPT as ad server backends. It wraps Relevant HB [JavaScript API](https://help.relevant-digital.com/knowledge/hb-manager#javascript-api) that includes:

- [xandr ad server](https://docs.xandr.com/)
- [Google GPT (google Publisher Tag)](https://developers.google.com/publisher-tag/guides/get-started)
- [Prebid ORG lib prebid.js](https://prebid.org/)
- [Relevant Analytics](https://help.relevant-digital.com/knowledge/hb-analytics)

## Related docs and access

- General [Help Center](https://help.relevant-digital.com/knowledge)
- [API](https://help.relevant-digital.com/knowledge/api-insights)
- [JavaScript API](https://help.relevant-digital.com/knowledge/hb-manager#javascript-api)
- [A/B Tests](https://help.relevant-digital.com/knowledge/a/b-testing-and-child-prebid-configurations)
- Relevant Ticket System [Relevant Digital's workspace](https://customer.to/relevant-digital/)

## Usage

```
npm install @smg-automotive/advertisement-pkg
```

### AdProvider

The library needs a few configuration variables to work. For that reason, you should wrap your page/top level app component with the `<AdProvider/>` context.

#### Configuring Alloy

To enable Alloy (optional), pass an `alloyConfig` prop to the `AdProvider`.

#### Configure ad-server tags to use with Relevant

You can only use one tag at a time - ASN or GPT:

- Microsoft ASN TAG: To set Relevant Digital with xandr ad-server by Microsoft ASN Tag set `astCdnUrl` with URL to ASN library CDN.
- **Google Ad Manager (GAM) / Google Publisher Tag (GPT):** Set `googleAdManagerCdnUrl` with the URL to the GPT library CDN. When using GPT, also pass `isGoogleTagUsed: true` to `useRelevantDigital` so the hook forwards it to the Relevant load.

**⚠️ NOTE: Native ad implementation in this library is working for ASN Tags only. GPT native ads are set on ad-server side.**

```tsx
import { AdProvider } from '@smg-automotive/advertisement-pkg';
import type { AlloyConfig } from '@smg-automotive/advertisement-pkg';

const alloyConfig: AlloyConfig = {
  alloyAppId: 'brand_ch_web', // {brand_name}_{web|ios|android|flutter} (e.g. autoscout24_ch_web)
  cdnUrl: 'https://cdn.alloy.ch/client-sdk/2.x.x/alloy-sdk.umd.js',
  env: 'prod', // or "stg"
  dataLayer: {
    context: {
      logicalPath: 'detail', // logical path of web site section (e.g. "home", "search", "detail"...). Note: alloyAppId is automatically added as prefix, resulting in format: {alloyAppId}/{logicalPath}
      contentId: '12345', // identifier of content currently shown on the page (e.g. listing ID). Note: Alloy team suggests only defining contentId for listing detail pages, for other pages set to empty string
    },
    user: {
      // optional
      sso: { id: 'user-123' }, // sso user identifier
      externalIds: { foo: 'bar' }, // external user's identifiers
    },
  },
  autostart: true, // optional, defaults to true. If false, window.alloySDK.start() is used for startup
  consentCookieName: 'eupubconsent-v2', // optional, defaults to eupubconsent-v2. Alloy SDK internally checks consent cookie and do not send data to server if there is no required consent
  preventProfiling: false, // optional, defaults to false. If set to true on mount, prevents Alloy script from being loaded
};

const App = () => (
  <AdProvider
    relevantDigitalConfigId="123abc"
    googleAdManagerCdnUrl="https://securepubads.g.doubleclick.net/tag/js/gpt.js"
    relevantDigitalCdnUrl="https://relevant-cdn/123abc.js"
    alloyConfig={alloyConfig}
    shouldInjectScriptsOnPageLoad={true} // used to inject ad scripts on page load to boost the ad performance
  >
    <AdSlot />
  </AdProvider>
);
```

### AdSlot component

The `AdSlot` component can be used to set two types of placements:

- Inactive placement(default): set on the page and invoked only when `useRelevantDigital` hook is called (invokes all inactive placements on the page). When this happens if you have mixed lazy and non-lazy loaded ads on page it will first initiate all non-lazy ones and in following request it will initiate the remaining lazy ones. On leaving the page hook will call [destroySlots](https://help.relevant-digital.com/knowledge/relevantdigital.destroyslots). Use whenever there is more than one inactive placement on page - this way you make one or possibly two (if some ads are lazy) calls to the relevant SDK to invoke all placements on a single page.
- Standalone placement: invoked on component render, does not require `useRelevantDigital` to get invoked, but requires keywords to be set. Can still be used on same page with inactive ads, in that case there is no need to call `destroySlots()` as hook will clean them all. If is not used on page with the hook, then it should be set to call `destroySlots()` on its own by setting the param `destroyOnUnmount` to `true`. Use when you absolutely must invoke ad on render. Example: In carousel, if ad is positioned later on the line, and you want to render it when the user swipes to it. Is also legit to be used if is only the single ad on the page and no more is planned to be added.

‼️⚠️ It is highly recommended to wrap the `AdSlot` component in [Error Boundary](https://legacy.reactjs.org/docs/error-boundaries.html). This will prevent errors to bubble out and crash other elements that are above in the hierarchy, possibly even the whole page or site.

#### Inactive AdSlot placements example (invoked by the hook)

When using GAM/GPT integration, pass `isGoogleTagUsed: true` to `useRelevantDigital` (see [Configure ad-server tags](#configure-ad-server-tags-to-use-with-relevant) above).

```tsx
import { AdSlot, useRelevantDigital } from '@smg-automotive/advertisement-pkg';

const keywords = { page: ['home'], site: ['yoursite.ch'], foo: 'bar' };

const HomePage = () => {
  useRelevantDigital({ keywords, isGoogleTagUsed: true });

  return (
    <div>
      <AdSlot adUnitId={1234567} id="home-top-banner" />
      {/* ... page content */}
      <AdSlot adUnitId={1234568} id="home-bottom-banner" />
    </div>
  );
};

export default HomePage;
```

#### Standalone AdSlot placement example (invoked on render)

```tsx
import { AdSlot, useRelevantDigital } from '@smg-automotive/advertisement-pkg';

const keywords = { page: ['brand'], site: ['yoursite.ch'], foo: 'bar' };

const BrandPage = () => {
  return (
    <div>
      <AdSlot
        adUnitId={1234567}
        id="brand-outside-right"
        standalone
        keywords={keywords}
        destroyOnUnmount
      />
    </div>
  );
};

export default BrandPage;
```

### Adjusting Native Add types

Native ads are configured by administrators and may change over time. To accommodate these changes and ensure type safety, you can adjust the types of native ads in your code using TypeScript generics.

```tsx
type CustomType = {
  customType: string;
};

const AdComponent: FunctionComponent<NativeAdComponentProps<CustomType>> = ({
  id,
  data,
}) => {
  return <div>{data.customType}</div>;
};

return (
  <div>
    <AdSlot<CustomType> nativeAdComponent={AdComponent} />
  </div>
);
```

### Lazy loading

Is set per placement slot in Relevant Yield dashboard for detailed instructions check here [Reloads and Lazy loads in HB Manager](https://help.relevant-digital.com/knowledge/reloads-in-hb-manager)

### Placement size depending on viewport size

Also covered in Relevant Yield dashboard.

### Debugging

Set URL param:

- `adpreview=dev` - displays ad placeholders with additional information like size, name, id ... etc.
- `?debugAdScripts` - activate debugging for `react-relevant` library together with prebid (`pbjs`) and xandr (`apntag`)
- `?ast_test` - we need to add when testing mobile web through simulation on a desktop device (else test with actual mobile device). Also if we suddenly start getting `AdBadRequest` on testing environment, we probably got blocked by Xandr, in that case we should add this to URL
- `?pbjs_debug` - debug prebid
- `?alydbg` - debug alloy
- `?google_debug` - GPT

Browser console:

- `googletag.openConsole()` - GPT

## Analytics

Is injected automatically with relevant ad-stack. Chances are that is already set, but if not check [Overview of setting up HB Analytics](https://help.relevant-digital.com/knowledge/how-to-setup-hb-analytics)
Can be customized per-site in Relevant Yield dashboard like: "Publisher accounts" > "SMG" (Edit button) > Tutti (or other site) "Programmatic tag" > expand "Custom Global JavaScript code". More in [Adding Custom Dimensions](https://help.relevant-digital.com/knowledge/adding-custom-dimensions)

## Development

```
npm run build
```

You can link your local npm package to integrate it with any local project:

```
cd advertisement-pkg
npm run build

cd <project directory>
npm link ../smg-automotive-example-pkg
```

## Release a new version

New versions are released on the ci using semantic-release as soon as you merge into master. Please
make sure your merge commit message adheres to the corresponding [conventions](https://www.conventionalcommits.org/en/v1.0.0/) and your branch name does not contain forward slashes `/`.