If your tenant uses Storyteller First Party Ads, you manage them in the
Storyteller CMS and don't change your integration code. The SDK loads and
shows these ads itself.
The SDK requests these ads from Google Ad Manager. For other ad servers,
contact the Storyteller Delivery Team.
Implement the getAdConfig callback on the global delegate
(IStorytellerDelegate, see StorytellerDelegate).
The SDK calls it each time it needs an ad, and only when your tenant uses
Google Ad Manager ads.
Assigning Storyteller.sharedInstance.delegate replaces every global
callback. The samples below spread the current delegate to keep your other
callbacks.
Storyteller.sharedInstance.delegate={...Storyteller.sharedInstance.delegate,getAdConfig:(adRequestInfo)=>{// Only Story ad requests have `story`. Clips ad requests have `clip`.constcustomTargeting=adRequestInfo.story?{storytellerStoryCategories:adRequestInfo.story.categories.map(({name})=>name),}:{storytellerClipCategories:adRequestInfo.clip.categories.map(({name})=>name),storytellerNextClipCategories:adRequestInfo.nextClip?.categories.map(({name})=>name)||[],};return{slot:'/30497361/your_ad_unit',publisherProvidedId:'your-publisher-provided-id',customTargeting,};},};
getAdConfig returns an object with the fields below, or null to request no
ad. An object without slot also requests no ad. Return the object directly:
the SDK doesn't wait for a promise. For the full type, see
getAdConfig in the callback reference.
Field
Description
slot
Required. The ID of your GAM ad unit, in the form /[NETWORK_CODE]/[UNIT_CODE]. The ad unit must serve 1x1 ads. For details, see Google's guides to custom ad creative and programmatic ad creative.
publisherProvidedId
Optional Publisher Provided ID (PPID) for Google Ad Manager. This value is sent as GAM's PPID field, not as a custom targeting KVP. The SDK trims whitespace, omits empty values, and omits this value when ad tracking is disabled.
customTargeting
Optional key-value pairs (KVPs) that the SDK sends to GAM for ad targeting. The SDK adds the default targeting values, and a key you return replaces the default key with the same name. The SDK doesn't copy KVPs that the rest of your page sets.
Values such as ddid, isLoggedIn, gdpr, us_privacy, gpp, gpp_sid,
and other app-owned ad/privacy KVPs should be supplied through
customTargeting. PPID should be supplied through publisherProvidedId.
customTargeting values can be strings or arrays of strings. Use arrays for
multi-value GAM KVPs so each value is passed as a distinct targeting value.
When ad tracking is off
(enableAdTracking: false), the SDK omits the default targeting and
publisherProvidedId. It still sends the customTargeting you return.
This object contains details about the Story or Clip the user is viewing. Pass
them to your ad server to target the ad. Only Story ad requests have story,
so check for it before you read it, as the samples above do.
A string which uniquely identifies the placement in which the Story is being shown
categories: string[]
A list of Category String IDs which have been assigned to the Stories list. Note that every Category in this list will appear on every Story in the list. This list can be useful to know in which context the user is currently viewing Stories.
story: ItemInfo
Metadata about the Story after which the requested Ad will be placed
The ItemInfo object has the following properties:
Property
Description
categories: CategoryDetail[]
An array of Categories which have been assigned to the Story
The CategoryDetail object has the following properties:
Property
Description
name: string
A human readable name for the Category
externalId: string
The external ID of the Category, set in the Storyteller CMS
A string which uniquely identifies the Collection that the Clips are assigned to
clip: ItemInfo
Metadata about the Clip after which the requested Ad will be placed
nextClip: ItemInfo
Optional. Metadata about the Clip that follows the Ad, when there is one
The ItemInfo object has the following properties:
Property
Description
categories: ClipCategory[]
An array of Categories which have been assigned to the Clip.
The ClipCategory object has the following properties:
Property
Description
name: string
A human readable name for the Category
externalId: string
The string ID for the Category
{"slug": "ads", "page_title": "Integrate Ads", "page_url": "Ads/", "canonical_url": "/web/Ads/", "markdown": "# Integrate ads\n\n<!-- markdownlint-disable MD033 -->\n<span id=\"ads\"><\/span>\n<span id=\"table-of-contents\"><\/span>\n\nStoryteller can show ads in Stories and Clips from two sources:\n\n- **First Party Ads**, which you create in the Storyteller CMS. They need no\n code.\n- **Google Ad Manager (GAM) ads**. Implement the `getAdConfig` callback to tell\n the SDK which ad unit to request and which targeting to send.\n\n## Ad Sources\n\nStoryteller sets which ad source your tenant uses. To change it, contact the\nStoryteller Delivery Team.\n\n## Storyteller First Party Ads\n\nIf your tenant uses Storyteller First Party Ads, you manage them in the\nStoryteller CMS and don't change your integration code. The SDK loads and\nshows these ads itself.\n\n## Google Ad Manager integration {#storyteller-ad-manager-integration}\n\nThe SDK requests these ads from Google Ad Manager. For other ad servers,\ncontact the Storyteller Delivery Team.\n\nImplement the `getAdConfig` callback on the global delegate\n(`IStorytellerDelegate`, see [StorytellerDelegate](StorytellerDelegate.md)).\nThe SDK calls it each time it needs an ad, and only when your tenant uses\nGoogle Ad Manager ads.\n\nAssigning `Storyteller.sharedInstance.delegate` replaces every global\ncallback. The samples below spread the current delegate to keep your other\ncallbacks.\n\n=== \"JavaScript\"\n\n ```javascript\n Storyteller.sharedInstance.delegate = {\n ...Storyteller.sharedInstance.delegate,\n getAdConfig: (adRequestInfo) => {\n // Only Story ad requests have `story`. Clips ad requests have `clip`.\n const customTargeting = adRequestInfo.story\n ? {\n storytellerStoryCategories: adRequestInfo.story.categories.map(({ name }) => name),\n }\n : {\n storytellerClipCategories: adRequestInfo.clip.categories.map(({ name }) => name),\n storytellerNextClipCategories:\n adRequestInfo.nextClip?.categories.map(({ name }) => name) || [],\n };\n\n return {\n slot: '/30497361/your_ad_unit',\n publisherProvidedId: 'your-publisher-provided-id',\n customTargeting,\n };\n },\n };\n ```\n\n=== \"TypeScript\"\n\n ```typescript\n import * as Storyteller from '@getstoryteller/storyteller-sdk-javascript';\n import type {\n StorytellerAdRequestInfo,\n StorytellerStoriesAdRequestInfo,\n } from '@getstoryteller/storyteller-sdk-javascript';\n\n function isStoryAd(\n adRequestInfo: StorytellerAdRequestInfo\n ): adRequestInfo is StorytellerStoriesAdRequestInfo {\n return 'story' in adRequestInfo;\n }\n\n Storyteller.sharedInstance.delegate = {\n ...Storyteller.sharedInstance.delegate,\n getAdConfig: (adRequestInfo) => {\n const customTargeting: Record<string, string[]> = isStoryAd(adRequestInfo)\n ? {\n storytellerStoryCategories: adRequestInfo.story.categories.map(({ name }) => name),\n }\n : {\n storytellerClipCategories: adRequestInfo.clip.categories.map(({ name }) => name),\n storytellerNextClipCategories:\n adRequestInfo.nextClip?.categories.map(({ name }) => name) || [],\n };\n\n return {\n slot: '/30497361/your_ad_unit',\n publisherProvidedId: 'your-publisher-provided-id',\n customTargeting,\n };\n },\n };\n ```\n\nThe Storyteller Web Showcase builds the `getAdConfig` result in\n[`buildAdConfig`](https://github.com/getstoryteller/storyteller-showcase-web/blob/11.0.0/nextjs/src/components/contexts/storytellerSdkDelegate.ts#L5)\nwith the ad slot and custom targeting values.\n\n### Return value {#return-value}\n\n`getAdConfig` returns an object with the fields below, or `null` to request no\nad. An object without `slot` also requests no ad. Return the object directly:\nthe SDK doesn't wait for a promise. For the full type, see\n[`getAdConfig` in the callback reference](reference/callbacks.md#getadconfig).\n\n| Field | Description |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `slot` | Required. The ID of your GAM ad unit, in the form `/[NETWORK_CODE]/[UNIT_CODE]`. The ad unit must serve 1x1 ads. For details, see Google's guides to [custom ad creative](https://support.google.com/admanager/answer/9038178?hl=en) and [programmatic ad creative](https://support.google.com/admanager/answer/9416436). |\n| `publisherProvidedId` | Optional Publisher Provided ID (PPID) for Google Ad Manager. This value is sent as GAM's PPID field, not as a custom targeting KVP. The SDK trims whitespace, omits empty values, and omits this value when ad tracking is disabled. |\n| `customTargeting` | Optional key-value pairs (KVPs) that the SDK sends to GAM for ad targeting. The SDK adds the [default targeting](#default-targeting) values, and a key you return replaces the default key with the same name. The SDK doesn't copy KVPs that the rest of your page sets. |\n\nValues such as `ddid`, `isLoggedIn`, `gdpr`, `us_privacy`, `gpp`, `gpp_sid`,\nand other app-owned ad/privacy KVPs should be supplied through\n`customTargeting`. PPID should be supplied through `publisherProvidedId`.\n\n`customTargeting` values can be strings or arrays of strings. Use arrays for\nmulti-value GAM KVPs so each value is passed as a distinct targeting value.\n\nWhen [ad tracking](PrivacyAndTracking.md#ad-tracking) is off\n(`enableAdTracking: false`), the SDK omits the default targeting and\n`publisherProvidedId`. It still sends the `customTargeting` you return.\n\n### Default Targeting\n\nBy default, the Storyteller SDK sets the following `customTargeting` values:\n\n#### Stories {#stories-default-targeting}\n\n| Property Name | Property Type | Description | Example value |\n| ------------------- | ------------- | --------------------------------------------------- | -------------------------------- |\n| `stCurrentCategory` | `string` | The external ID of the current Story Category. | \"top-stories\" |\n| `stPlacement` | `string` | The placement `code` of the current Story Category. | `web-top-stories` |\n| `stCategories` | `string[]` | External IDs of the current Story Categories. | `[\"top-stories\", \"web-stories\"]` |\n\n#### Clips {#clips-default-targeting}\n\n| Property Name | Property Type | Description | Example value |\n| ---------------------- | ------------- | -------------------------------------------- | ---------------------------- |\n| `stCollection` | `string` | The ID of the current Clip Collection. | `live-clips` |\n| `stClipCategories` | `string[]` | External IDs of the current Clip Categories. | `[\"top-clips\", \"web-clips\"]` |\n| `stNextClipCategories` | `string[]` | External IDs of the next Clip Categories. | `[\"top-clips\", \"web-clips\"]` |\n\n### AdRequestInfo\n\nThe `StorytellerAdRequestInfo` object passed to this callback can be one of two\ntypes, depending on whether the user is viewing Stories or Clips:\n\n```typescript\nexport type StorytellerStoriesAdRequestInfo = {\n placement: string;\n categories: string[];\n story: {\n categories: CategoryDetail[];\n };\n};\n\nexport type StorytellerClipsAdRequestInfo = {\n collection: string;\n clip: {\n categories: ClipCategory[];\n };\n nextClip?: {\n categories: ClipCategory[];\n };\n};\n```\n\nThis object contains details about the Story or Clip the user is viewing. Pass\nthem to your ad server to target the ad. Only Story ad requests have `story`,\nso check for it before you read it, as the samples above do.\n\n#### Stories {#stories-adrequestinfo}\n\nStory ad requests contain:\n\n| Property | Description |\n| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `placement: string` | A string which uniquely identifies the placement in which the Story is being shown |\n| `categories: string[]` | A list of Category String IDs which have been assigned to the Stories list. Note that every Category in this list will appear on every Story in the list. This list can be useful to know in which context the user is currently viewing Stories. |\n| `story: ItemInfo` | Metadata about the Story after which the requested Ad will be placed |\n\nThe `ItemInfo` object has the following properties:\n\n| Property | Description |\n| ------------------------------ | ------------------------------------------------------------ |\n| `categories: CategoryDetail[]` | An array of Categories which have been assigned to the Story |\n\nThe `CategoryDetail` object has the following properties:\n\n| Property | Description |\n| -------------------- | ----------------------------------------------------------- |\n| `name: string` | A human readable name for the Category |\n| `externalId: string` | The external ID of the Category, set in the Storyteller CMS |\n\n#### Clips {#clips-adrequestinfo}\n\nClips ad requests contain:\n\n| Property | Description |\n| -------------------- | -------------------------------------------------------------------------------- |\n| `collection: string` | A string which uniquely identifies the Collection that the Clips are assigned to |\n| `clip: ItemInfo` | Metadata about the Clip after which the requested Ad will be placed |\n| `nextClip: ItemInfo` | Optional. Metadata about the Clip that follows the Ad, when there is one |\n\nThe `ItemInfo` object has the following properties:\n\n| Property | Description |\n| ---------------------------- | ------------------------------------------------------------ |\n| `categories: ClipCategory[]` | An array of Categories which have been assigned to the Clip. |\n\nThe `ClipCategory` object has the following properties:\n\n| Property | Description |\n| -------------------- | -------------------------------------- |\n| `name: string` | A human readable name for the Category |\n| `externalId: string` | The string ID for the Category |\n", "copy_markdown_include_header": false, "base_path": "", "ai_dir": "ai", "missing_payload_behavior": "empty"}