---
title: AdSpirit Integration
slug: experience/adspirit-integration
docTags: 
createdAt: 2025-02-12T13:09:10.052Z
---

AdSpirit is a trusted ad platform for premium publishers. This guide will cover the key setup steps, configuration options, and best practices to ensure a smooth and compliant integration.&#x20;

***

## Preconditions

Before starting the integration, ensure you have the following resources ready:

1. **AdSpirit script url:** proper script url (usually it is default for all: [https://cdn.adspirit.de/adasync.min.js](https://cdn.adspirit.de/adasync.min.js))
2. **List of ads** and there corresponding placements for desktop and mobile in design
3. **Consent Management**: Ensure the CMP (Consent Management Platform) is configured with vendors relevant to AdSpirit (including IAB-compliant vendor IDs): "cdn.adspirit.de",
   "apoverlag.adspirit.de".
4. Use PXP version 3.8.8 and higher

**Important Notes:**

- AdSpirit ads can be tested even at localhost without any additional queryparams or configuration
- We don't need to trigger any consent given event, while AdSpirit reads it on their side
- AdSpirit require adsRefresh
- Some customers use subscribtion plans to disable ads
- List of available ads with their ids [https://adsprit-example.glitch.me/](https://adsprit-example.glitch.me/)
- **!!!** If conditional loading of ads for proper screens needed we need to have conditional loading in view\.json **relying on $context.device\_type** and **not  a css based condition with display: block/none**
-

***

## How-to guide

### 1. Experience Config

- Go to Experience Builder. Create or edit experience config `default/storefront/assets/experience.config.json`
- As AdSpirit manages consent on their side we don't need to add additional consent configuration to purple.ads.consent (for other ad services, which is not audienzz you might need to add vendorId and iabVendorId. You find vendorId in your consent manager configurations and find iabVendorId here [https://iabeurope.eu/vendor-list-tcf/](https://iabeurope.eu/vendor-list-tcf/))
- In ads.adspirit.configuration add proper script id `adspirit-header-script` and url [`https://cdn.adspirit.de/adasync.min.js`](https://cdn.adspirit.de/adasync.min.js).&#x20;
- To refresh AdSpirit ads dynamically, we need access to the **loaded AdSpirit script**.
  - AdSpirit provides its API via **asm\_async\_data**, which is **a standard global object** after the script loads.
  - We must **pass asm\_async\_data** as the `scriptWinKey` to reference it correctly.
- To **hide ads for subscribed users**, we need to check for a specific window key that indicates whether the user is a premium subscriber.&#x20;
  - The **window key varies by project**.
  - In the **latest project**, this key is `cmp_pur_loggedin`.
  - If `window[cmp_pur_loggedin]` is true, **ads should not be shown**.

:::BlockQuote
\{
"language": "de",
"purple": \{
&#x20; "version": \{
&#x20;   "major": 1,
&#x20;   "minor": 0
&#x20; },
&#x20; "ads": \{
&#x20;     "adspirit": \{
&#x20;       "configuration": \{
&#x20;         "headerScriptId": "adspirit-header-script",
&#x20;         "headerScriptUrl": "https\://cdn.adspirit.de/adasync.min.js",
&#x20;         "scriptWinKey": "asm\_async\_data",
&#x20;         "premiumSubWinKey": "cmp\_pur\_loggedin"        }
&#x20;     }
&#x20; }
}
}
:::

### &#xA;2\. In `default/storefront/assets`, click on the 'ads.json' file, or create one.&#x20;



![](https://api.archbee.com/api/optimize/ygR6KtT9QI_R0u3uKTJsm/5weYcTZTQgHDI17jXUYBB_image.png)

:::BlockQuote
\{
&#x20; "adSlots": \[
&#x20;   \{
&#x20;     "id": "adspirit-desktop-superbanner-272",
&#x20;     "providerConfig": \{
&#x20;       "id": "272",
&#x20;       "type": "ADSPIRIT",
&#x20;       "height": 110,
&#x20;       "params": "$function.customChecker($context.adSpiritParams)",
&#x20;       "platform": "desktop",
&#x20;       "spaceTop": 2,
&#x20;       "width": 1058,
&#x20;       "spaceBottom": 1
&#x20;     },    \{
&#x20;     "id": "adspirit-mobile-header-270",
&#x20;     "providerConfig": \{
&#x20;       "id": "272",
&#x20;       "type": "ADSPIRIT",
&#x20;       "params": "$function.customChecker($context.adSpiritParams)",
&#x20;       "platform": "mobile tablet",
&#x20;       "spaceTop": 2,
&#x20;       "spaceBottom": 1
&#x20;     }
&#x20;   }
&#x20;   }
&#x20; ]
}
:::

- top level id can be anything specific to project.&#x20;
- params resides in content.properties\["adspirit.urlparameters"] coming from hub, should be set in builder as $context.adSpiritParams. In url.resolver.json it can be set per article, and not per home page for example, so to properly handle this use some **$function.customChecker($context.adSpiritParams)** to resolve to empty string if there is no $context.adSpiritParams defined. Example of setting of those adSpiritParams in url.resolver.json:

:::BlockQuote
// url.resolver.json

**const setAdspiritParams = (content) => \{
&#x20; let params = "";
&#x20; if (
&#x20;   content &&
&#x20;   content.properties &&
&#x20;   content.properties &&
&#x20;   content.properties\["adspirit.urlparameters"]
&#x20; ) \{
&#x20;   params = content.properties\["adspirit.urlparameters"];
&#x20; }
&#x20; return params;
};**

const handleArticle = async (\{ match, dataResolver, resolvedData }) => \{
&#x20; ... rest of the code ...
&#x20; const articleSlug = getArticleSlug(match);
&#x20; const postContents = resolvedData\[articleSlug].contents;

&#x20; if (!postContents.length) \{
&#x20;   return \{ notFound: true };
&#x20; }
&#x20; const content = await dataResolver.findContentById(postContents\[0].id);

&#x20; ... rest of the code ...
&#xA;**&#x20; const adSpiritParams = setAdspiritParams(content);**

&#x20; ... rest of the code ...
&#x20;
&#x20; return \{
&#x20;   viewName: VIEW\_NAMES.ARTICLE\_DEFAULT,
&#x20;   viewContext: \{
&#x20;     content,
&#x20;     ... rest of the code ...&#xA;**&#x20;     adSpiritParams,**
&#x20;     ... rest of the code ...
&#x20;   },
&#x20; };
};
:::

### 3. Final created Ad Element Structure

**NOTE:** This section is just to see what will be our resulted add from above configurations (no configurations part here)
With crossed items to be configurable:

1\) ~~*mobile tablet*~~ - platform (it could be "desktop", "mobile", "tablet", "large-desktop" or combined "mobile tablet") if configured in .scss file *(check&#x20;*&#x61;dspirit.scss file mentioned belo&#x77;*). This classes should not be used for conditional showing of the ads with display: block/none.*
2\) ~~*space-top-1 space-bottom-2*~~*&#x20;- configurations are also added in scss file for proper styling (check&#x20;*&#x61;dspirit.scss file mentioned belo&#x77;*)*~~**~~
3\) pid=~~*12345*~~*&#x20;- id of the ad. Proper ads and their ids can be found&#x20;*[here](https://adsprit-example.glitch.me/)**
4\) ~~*param1=value1*~~*&#x20;-&#x20;*&#x63;ould be something like "special=no\_ad" and should be configured through builder and placed in from *content.properties\["adspirit.urlparameters"]* to *$context.adSpiritUrlParams* or something similar. Can be added with or without "&" at the beginning of the string, other params add should match "&" structure in between of each query param "special=no\_a&#x64;**&**&#x70;aram1=value1".**
*5) styles width:&#x20;*~~*300px&#x20;*~~*& height:&#x20;*~~*auto*~~ - width and height if not provided will be `100%` and `auto `respectevely. You should set them as number without px.

:::BlockQuote
\<div class="ad ~~*mobile tablet*~~"> \<!-- Container element for the ad where platform config should be added like "mobile tablet"-->
&#x20;   \<div class="ad-content ~~*space-top-1 space-bottom-2*~~">
&#x20;       \<div class="ad-content-inner">
&#x20;           \<ins class="asm\_async\_creative"&#x20;
&#x20;                style="width: ~~*300px*~~; height:~~*&#x20;auto*~~; text-align: left; text-decoration: none;"&#x20;
&#x20;                data-asm-cdn="cdn.adspirit.de"&#x20;
&#x20;                data-asm-host="apoverlag.adspirit.de"&#x20;
&#x20;                data-asm-params="pid=~~*12345\&param1=value1*~~">
&#x20;           \</ins>
&#x20;           \<span class="ad-badge">Anzeige\</span>
&#x20;       \</div>
&#x20;   \</div>
\</div>
:::

### 4. When adding to your page. Add item in proper place:

![](https://api.archbee.com/api/optimize/ygR6KtT9QI_R0u3uKTJsm/xUBJ_BTSZmm4n1Ln4EuU8_image.png "select Ad item")



![](https://api.archbee.com/api/optimize/ygR6KtT9QI_R0u3uKTJsm/TQq-jhP4MaxZsact6P0bP_image.png)

We should use conditional loading of mobile/tablet or desktop ads (check if project handles proper screen types like $context.device\_type):

:::BlockQuote
\[
&#x20; \{
&#x20;   "adId": "adspirit-desktop-superbanner-272",
&#x20;   "type": "ad",
&#x20;   "condition": \{
&#x20;     "AND": \[
&#x20;       \{
&#x20;         "value": "$context.device\_type",
&#x20;         "operation": "EQUALS\_NOT",
&#x20;         "compareValue": "phone"
&#x20;       },
&#x20;       \{
&#x20;         "value": "$context.device\_type",
&#x20;         "operation": "EQUALS\_NOT",
&#x20;         "compareValue": "tablet"
&#x20;       }
&#x20;     ]
&#x20;   }
&#x20; },
&#x20; \{
&#x20;   "adId": "adspirit-mobile-header-270",
&#x20;   "type": "ad",
&#x20;   "condition": \{
&#x20;     "OR": \[
&#x20;       \{
&#x20;         "value": "$context.device\_type",
&#x20;         "operation": "EQUALS",
&#x20;         "compareValue": "phone"
&#x20;       },
&#x20;       \{
&#x20;         "value": "$context.device\_type",
&#x20;         "operation": "EQUALS",
&#x20;         "compareValue": "tablet"
&#x20;       }
&#x20;     ]
&#x20;   }
&#x20; }
]
:::

### 5. You can also have styles configurations

You can apply your ad specific styles like this:
/src/default/storefront/assets/scss/adspirit.scss


:::BlockQuote
@use "./common-ui" as \*;
@use "./media-query" as \*;

.ad \{

&#x20; \--ad-badge-height: 15px;
&#x20; \--ad-badge-padding-left: 4px;
&#x20; \--ad-badge-padding-right: 4px;
&#x20; \--ad-badge-font-size: 10px;
&#x20; \--ad-badge-font-style: normal;
&#x20; \--ad-badge-font-weight: 400;
&#x20; \--ad-badge-line-height: 13px;
&#x20; \--ad-badge-dark-color: white;
&#x20; \--ad-badge-dark-background: #68626280;
&#x20; \--ad-badge-light-background: #ffffff80;
&#x20; \--ad-badge-light-color: #686262;
&#x20; \--ad-content-inner-margin-left: auto;
&#x20; \--ad-content-inner-margin-right: auto;

&#x20; \--space-1: 15px;
&#x20; \--space-2: 30px;


&#x20; @include media-xlarge \{
&#x20;   \--ad-badge-font-size: 12px;
&#x20;   \--ad-badge-line-height: 15px;
&#x20; }
}

.ad \{
&#x20; display: block;
&#x20; position: relative;
}

.lg\\\:hidden \{
&#x20; @include media-large \{
&#x20;   display: none;
&#x20; }
}

.ad-badge \{
&#x20; height: var(--ad-badge-height);
&#x20; padding-left: var(--ad-badge-padding-left);
&#x20; padding-right: var(--ad-badge-padding-right);
&#x20; font-size: var(--ad-badge-font-size);
&#x20; font-style: var(--ad-badge-font-style);
&#x20; font-weight: var(--ad-badge-font-weight);
&#x20; line-height: var(--ad-badge-line-height);
&#x20; position: absolute;
&#x20; top: 0;
&#x20; right: 0;
&#x20; z-index: 123;
&#x20; background: var(--ad-badge-dark-background);
&#x20; color: var(--ad-badge-dark-color);
&#x20; text-align: right;
}

.ad-content \{
&#x20; overflow-x: hidden;
&#x20; display: flex;
&#x20; justify-content: start;
}

.ad-content-inner \{
&#x20; margin-left: var(--ad-content-inner-margin-left);
&#x20; margin-right: var(--ad-content-inner-margin-right);
&#x20; position: relative;
}

.asm\_async\_creative \{
&#x20; position: relative;
}

.ad-content.space-top-1 \{
&#x20; margin-top: var(--space-1);
}

.ad-content.space-top-2 \{
&#x20; margin-top: var(--space-2);
}

.ad-content.space-bottom-1 \{
&#x20; margin-bottom: var(--space-1);
}

.ad-content.space-bottom-2 \{
&#x20; margin-bottom: var(--space-2);
}

.ad-ressort-previews \{
&#x20; max-width: calc(100% - var(--side-bar-width));
}

.ad-end-of-article \{
&#x20; padding-left: var(--outer-gutters);
}
:::

### 6. Configure Ads placement in your project according to Mockups

### 7. Notes

- Native Ads are currently not covered in Pxp code
- Swiper Ads are not covered in Pxp code

