Custom Popups Erstellen
Custom Activation Pop-up (HTML & CSS) – Anleitung
Überblick
Für Activation Pop-ups bieten wir eine Custom-Pop-up-Funktion, bei der Kund:innen das Pop-up frei über eigenes HTML und CSS gestalten können.
Uptain stellt dafür ein HTML-Grundgerüst und Beispiel-CSS bereit, das als Ausgangspunkt dient und individuell angepasst werden kann.
Typische Use Cases:
Voucher-/Gutschein-Pop-up
Abbruch-/Exit-Intent Pop-up
Aktivierung eines Rabattcodes per Klick oder automatisch
Wie funktioniert das Custom Pop-up?
Das Pop-up besteht aus:
HTML-Struktur
definiert die Inhalte (z. B. Gutschein-Code, Buttons, Text, Close-Icon)
CSS / Styling
bestimmt Layout, Größe, Position, Hintergrundbild etc.
responsive über Breakpoints (Mobile / Tablet / Desktop)
Dynamische Inhalte
können per Platzhalter eingebunden werden (z. B.
{{voucherCode}})
0) Wichtige Einstellungen & Trigger (vor dem Start)
Bevor das Custom Pop-up gestaltet wird, sollten die wichtigsten Einstellungen korrekt gewählt werden, da diese maßgeblich beeinflussen, wann und wie das Pop-up ausgespielt wird.
Regain Type (Tracking-Logik)
Bestimmt, wann ein Erfolg (Regain) gezählt wird:
Voucher: Regain wird nur gezählt, wenn der Gutschein tatsächlich eingelöst wird (empfohlen für Gutschein-Pop-ups)
Shown: Regain wird bereits beim Anzeigen des Pop-ups gezählt
Manual: Regain wird erst nach einer aktiven Nutzerinteraktion gezählt (z. B. Klick auf ein Element)
Trigger (Ausspielung des Pop-ups)
Definiert, wann das Pop-up erscheint:
Desktop: empfohlen sind MouseOutV2 und Tab Idle
Mobile: empfohlen sind TapIdle (kein klassischer Mouse-Out verfügbar)
Weitere Trigger sollten nur gezielt eingesetzt werden, um zu häufige oder unpassende Ausspielungen zu vermeiden
Fallback Trigger
Optional – kann leer bleiben oder ebenfalls auf MouseOutV2 gesetzt werden.
Blocking Time
Kann leer bleiben (Standardverhalten). Wird genutzt, um zu verhindern, dass Nutzer das Pop-up zu häufig sehen.
Template-Referenzen (z. B. Activation Mail Template)
Diese Felder sind für Custom Pop-ups in der Regel nicht relevant und können leer bleiben.
💡 Best Practice:
Für klassische Gutschein-Pop-ups empfiehlt sich:
Regain Type: Voucher
Desktop Trigger: Mouse Out V2 + Tab Idle
Mobile Trigger: Tap Idle
1) HTML – Grundstruktur
Das folgende HTML wird im Custom-Pop-up hinterlegt:
<div class="__up_activation">
<div id="__up_pop_bg" class="__up_background __up_hidden" data-up-close-event="background"></div>
<div class="__up_pop __up_hidden __up_visible">
<button type="button" class="__up_close __up_close_button __up_close_icon" data-up-close-event="close-x">×</button>
<div class="__up_action">
<input type="text" class="__up_code_value" value="{{voucherCode}}">
</div>
</div>
</div>Wichtige Bestandteile
__up_pop_bg
→ Background/Overlay (dunkler Hintergrund), wird ebenfalls fürs Schließen genutzt.__up_pop
→ Container des eigentlichen Pop-ups.Close Button
→ Schließt das Pop-up (überdata-up-close-event="close-x").{{voucherCode}}
→ Dynamischer Gutschein-Code (Platzhalter wird von Uptain gefüllt).Sollte kein Code Vorhanden sein kann die gesamte Code Linie entfernt werden
✅ Hinweis: Die CSS-Klassen sind notwendig, damit Uptain die Elemente korrekt erkennt und steuern kann.
2) CSS – Beispiel-Styling
Wir stellen Beispiel-CSS bereit, das Kund:innen verwenden und anpassen können.
Das Styling nutzt mehrere Variablen, um Anpassungen einfacher zu machen.
A) Muss-Anpassungen (sehr wichtig)
✅ 1. Hintergrundbild ersetzen
In den Variablen:
@popupWidthMobile: 375px;
@popupWidthTablet: 440px;
@popupWidthDesktop: 450px;
@popupHeightMobile: 246px;
@popupHeightTablet: 295px;
@popupHeightDesktop: 295px;
@backgroundImageDesktop: url('https://test.de/Zwischenablage5.jpg?ts=1740392776');
@backgroundImageMobile: url('https://test.de/Zwischenablage5.jpg?ts=1740392776');
@codeTopOffsetMobile: 132px;
@codeTopOffsetTablet: 162px;
@codeTopOffsetDesktop: 162px;
@codeLeftOffsetMobile: 20px;
@codeLeftOffsetTablet: 20px;
@codeLeftOffsetDesktop: 25px;
@codeMaxWidthMobile: 195px;
@codeMaxWidthTablet: 195px;
@codeMaxWidthDesktop: 195px;
@codeFontSizeMobile: 16px;
@codeFontSizeTablet: 16px;
@codeFontSizeDesktop: 16px;
@codeLineHeightMobile: 16px;
@codeLineHeightTablet: 16px;
@codeLineHeightDesktop: 16px;
@codeFontColor: #555;
@codePlaceholderColor: #555;
@closeButtonSize: 24px;
@closeButtonTopOffsetMobile: 12px;
@closeButtonTopOffsetTablet: 14px;
@closeButtonTopOffsetDesktop: 14px;
@closeButtonRightOffsetMobile: 12px;
@closeButtonRightOffsetTablet: 14px;
@closeButtonRightOffsetDesktop: 14px;
@closeButtonColor: #333;
.__up_pop_bg {
position: fixed;
top: 0;
left: 0;
opacity: 0;
visibility: hidden;
width: 100%;
height: 100%;
z-index:9998;
background-color:rgba(0,0,0,0.7);
transition:visibility .5s, opacity .75s linear;
}
.__up_pop_bg.__up_visible{
opacity:1;
visibility:visible;
pointer-events:auto;
}
.__up_pop {
width: @popupWidthMobile;
height: @popupHeightMobile;
position: fixed;
left: 50%;
top: 50%;
transform: translateX(0);
-webkit-transform: translateX(0);
z-index: 10000;
}
.__up_pop.__up_visible {
animation-duration: .5s;
-webkit-animation-name: open-pop;
animation-name: open-pop;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
animation-delay: 0s
}
.__up_pop:before {
content: '';
display: block;
position: relative;
width: 100%;
height: 100%;
background-image: @backgroundImageMobile;
background-size: cover;
background-position: bottom center;
background-repeat: no-repeat;
}
@media screen and (min-width: 440px) {
.__up_pop {
width: @popupWidthTablet;
height: @popupHeightTablet;
}
}
@media screen and (min-width: 756px) {
.__up_pop {
width: @popupWidthDesktop;
height: @popupHeightDesktop;
}
.__up_pop:before {
position: absolute;
background-image: @backgroundImageDesktop;
background-position: center left;
}
}
.__up_action {
position: absolute;
text-align: left;
max-width: @codeMaxWidthMobile;
left: @codeLeftOffsetMobile;
top: @codeTopOffsetMobile;
width: 100%;
display: flex;
align-items: stretch;
justify-content: space-between;
}
@media screen and (min-width: 440px) {
.__up_action {
top: @codeTopOffsetTablet;
transform: translateX(0);
left: @codeLeftOffsetTablet;
max-width: @codeMaxWidthTablet;
}
}
@media screen and (min-width: 756px) {
.__up_action {
top: @codeTopOffsetDesktop;
left: @codeLeftOffsetDesktop;
max-width: @codeMaxWidthDesktop;
}
}
.__up_pop input::-webkit-input-placeholder {
color: @codePlaceholderColor;
}
.__up_pop input:-moz-placeholder {
color: @codePlaceholderColor;
}
.__up_pop input::-moz-placeholder {
color: @codePlaceholderColor;
}
.__up_pop input:-ms-input-placeholder {
color: @codePlaceholderColor;
}
.__up_action_button {
background: #c0bc69;
border: 0;
border-radius: 0 4px 4px 0;
color: #fff;
padding: 0 16px;
cursor: pointer;
transition: all 300ms ease;
}
input.__up_code_value {
background: none;
border: none;
box-shadow: none;
border-radius: 4px 0 0 4px;
width: 100%;
color: @codeFontColor;
box-sizing: border-box;
transition: all 300ms ease;
line-height: @codeLineHeightMobile;
font-size: @codeFontSizeMobile;
padding: 12px 8px 12px 16px;
border-right: 0;
position: relative;
}
@media screen and (min-width: 440px) {
input.__up_code_value {
line-height: @codeLineHeightTablet;
font-size: @codeFontSizeTablet;
}
}
@media screen and (min-width: 756px) {
input.__up_code_value {
line-height: @codeLineHeightDesktop;
font-size: @codeFontSizeDesktop;
}
}
input.__up_code_value:focus-visible {
outline: #eee;
}
input.__up_code_value.__up_code_input_copied {
border-color: #c0bc69;
}
input.__up_code_value.__up_code_input_copied + .__up_action_button {
text-shadow: 1px 1px 2px #e1e0b4;
}
.__up_close_button {
position: absolute;
right: @closeButtonRightOffsetMobile;
top: @closeButtonTopOffsetMobile;
color: @closeButtonColor;
background: none;
border: none;
font-size: @closeButtonSize;
line-height: @closeButtonSize;
padding: 0;
z-index: 1;
transition: all 300ms ease;
cursor: pointer;
}
@media screen and (min-width: 440px) {
.__up_close_button {
right: @closeButtonRightOffsetTablet;
top: @closeButtonTopOffsetTablet;
}
}
@media screen and (min-width: 756px) {
.__up_close_button {
right: @closeButtonRightOffsetDesktop;
top: @closeButtonTopOffsetDesktop;
}
}
.__up_close_button:hover {
transform: scale(1.15);
}
@keyframes open-pop {
0% {
opacity: 0;
transform: translate(-50%, -50%) scale(0);
-webkit-transform: translate(-50%, -50%) scale(0)
}
100% {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
-webkit-transform: translate(-50%, -50%) scale(1)
}
}
@keyframes close-pop {
0% {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
-webkit-transform: translate(-50%, -50%) scale(1)
}
100% {
opacity: 0;
transform: translate(-50%, -50%) scale(0);
-webkit-transform: translate(-50%, -50%) scale(0)
}
}A) Muss-Anpassungen (sehr wichtig)
✅ 1. Hintergrundbild ersetzen
In den Variablen:
@backgroundImageDesktop: url('https://.../bild.jpg');
@backgroundImageMobile: url('https://.../bild.jpg');
➡ Kund:innen müssen diese URLs unbedingt ersetzen, wenn sie ein eigenes Hintergrundbild nutzen möchten.
Tipp:
Desktop: Querformat / größere Auflösung
Mobile: optimiertes Bild für Mobile (z. B. kürzerer Fokus, besserer Crop)
✅ 2. Pop-up-Größe prüfen und ggf. anpassen
Die Default-Werte sind:
@popupWidthMobile: 375px;
@popupWidthTablet: 440px;
@popupWidthDesktop: 450px;
@popupHeightMobile: 246px;
@popupHeightTablet: 295px;
@popupHeightDesktop: 295px;
➡ Kund:innen sollten diese Werte überprüfen, wenn:
das Hintergrundbild andere Maße hat
Inhalte abgeschnitten werden
Buttons/Inputs nicht passen
B) Inhalt positionieren (Gutschein-Code / Elemente)
Der Bereich .__up_action ist das Element, das den Gutschein-Code enthält.
Positionierung erfolgt über:
@codeTopOffsetMobile: 132px;
@codeTopOffsetTablet: 162px;
@codeTopOffsetDesktop: 162px;
@codeLeftOffsetMobile: 20px;
@codeLeftOffsetTablet: 20px;
@codeLeftOffsetDesktop: 25px;
@codeMaxWidthMobile: 195px;
@codeMaxWidthTablet: 195px;
@codeMaxWidthDesktop: 195px;
➡ Das ist typischerweise der wichtigste Bereich, den Kund:innen anpassen müssen, damit:
Input exakt über einem “Code-Feld” im Hintergrundbild liegt
oder generell richtig platziert ist
So geht’s:
@codeTopOffset…→ verschiebt nach unten/oben@codeLeftOffset…→ verschiebt nach links/rechts@codeMaxWidth…→ max. Breite des Code-Containers
3) Buttons und Input (Styling & Anpassungen)
A) Input-Feld anpassen
Das Input-Feld:
input.__up_code_value { ... }
Anpassbar sind u. a.:
font-size,line-heightpaddingTextfarbe via
@codeFontColorPlaceholder-Farbe via
@codePlaceholderColor
Beispiel:
@codeFontColor: #555;
@codePlaceholderColor: #555;
➡ Wenn der Gutschein-Code auf dem Hintergrund zu schlecht lesbar ist, sollte hier ein höherer Kontrast gewählt werden.
4) Close Button (Position, Farbe, Größe)
Close Button: .__up_close_button
Wichtige Variablen:
@closeButtonSize: 24px;
@closeButtonTopOffsetMobile: 12px;
@closeButtonRightOffsetMobile: 12px;
@closeButtonTopOffsetTablet: 14px;
@closeButtonRightOffsetTablet: 14px;
@closeButtonTopOffsetDesktop: 14px;
@closeButtonRightOffsetDesktop: 14px;
@closeButtonColor: #333;
➡ Wenn Kund:innen den Button versetzen möchten:
@closeButtonTopOffset…@closeButtonRightOffset…
➡ Wenn er zu klein/groß ist:
@closeButtonSize
5) Responsives Verhalten (Mobile / Tablet / Desktop)
Das Pop-up arbeitet mit Breakpoints:
Mobile: Standard
Tablet:
min-width: 440pxDesktop:
min-width: 756px
Damit können:
Pop-up-Größe
Background-Image
Positionen des Inputs
je nach Gerät getrennt gesteuert werden.
Beispiel:
@media screen and (min-width: 756px) {
.__up_pop:before {
background-image: @backgroundImageDesktop;
}
}
✅ Wichtig: Kund:innen sollten Desktop- & Mobile-Hintergrundbild getrennt optimieren, weil sonst Cropping/Lesbarkeit nicht passt.
Bounce Popup MVP
<div class="__up_activation">
<div class="__up_background __up_hidden" id="__up_pop_bg" data-up-close-event="background"></div>
<div class="__up_pop __up_hidden">
<svg
class="__up_close_icon"
data-up-close-event="close-x"
id="Ebene_1"
data-name="Ebene 1"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
>
<path
d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z"
fill="black"
/>
</svg>
<div class="__up_pop_content">
<h2 class="__up_header_text">Sichere dir jetzt</h2>
<h1 class="__up_headline_text">
5 € Rabatt
</h1>
<h2 class="__up_underline_text">auf diesen Einkauf.*</h2>
<div class="__up_action">
<div class="__up_code_wrapper">
<input id="__up_code_value" readonly type="text" class="__up_code_value" value="{{dynamicVoucherCode}}"/>
<label for="__up_code_value" class="__up_code_value_input_label">Gutscheincode</label>
<button
class="__up_action_button"
onclick="
navigator.clipboard.writeText(document.getElementById('__up_code_value').value)
.then(() => this.textContent = 'GUTSCHEIN KOPIERT!');
"
data-up-event="copy"
>
GUTSCHEIN KOPIEREN
</button>
</div>
</div>
<div class="__up_dismiss" data-up-close-event="dismiss">Nein danke, ich möchte keinen Gutschein.</div>
<div class="__up_footer">* Nur für Neukunden, 100€ Mindestbestellwert, nicht kombinierbar mit anderen Gutschein- oder Rabattcodes, kann nicht für den Kauf von Büchern oder Geschenkgutscheinen verwendet werden. Eine Eingabe bei Zahlung mit PayPal Express technisch nicht möglich.</div>
</div>
</div>
</div>
@buttonColor: rgba({{buttonColor.r}}, {{buttonColor.g}}, {{buttonColor.b}}, {{buttonColor.a}});
@buttonFontColor: rgba({{buttonFontColor.r}}, {{buttonFontColor.g}}, {{buttonFontColor.b}}, {{buttonFontColor.a}});
@headingColor: rgba({{headingColor.r}}, {{headingColor.g}}, {{headingColor.b}}, {{headingColor.a}});
@inputColor: rgba({{inputColor.r}}, {{inputColor.g}}, {{inputColor.b}}, {{inputColor.a}});
@textColor: rgba({{textColor.r}}, {{textColor.g}}, {{textColor.b}}, {{textColor.a}});
@font-family: '{{font}}', 'Helvetica Neue', Arial;
@font-family-bold: '{{fontBold}}', 'Helvetica Neue', Arial;
@backgoundColor: rgba({{backgroundColor.r}}, {{backgroundColor.g}}, {{backgroundColor.b}}, {{backgroundColor.a}});
@buttonHoverColor: hsl(from @buttonColor h 76 47);
@buttonFocusColor: hsl(from @buttonColor h s 67);
#__up_pop_bg {
position: fixed;
top: 0;
left: 0;
opacity: 0;
}
.__up_activation {
box-sizing: initial;
text-align: left;
line-height: 1;
.__up_background {
pointer-events: none;
visibility: hidden;
display: block;
height: 100%;
width: 100%;
z-index: 9998;
top: 0;
left: 0;
opacity: 0;
backdrop-filter: blur(4px);
background-color: rgba(0, 0, 0, 0.4);
@keyframes background-open {
0% {
opacity: 0;
visibility: hidden;
pointer-events: none;
}
100% {
opacity: 1;
visibility: visible;
pointer-events: auto;
}
}
@keyframes background-close {
0% {
opacity: 1;
visibility: visible;
pointer-events: auto;
}
100% {
opacity: 0;
visibility: hidden;
pointer-events: none;
}
}
&.__up_visible {
animation-duration: 0.5s;
animation-name: background-open;
animation-fill-mode: both;
animation-delay: 0s;
}
&.__up_hidden {
animation-duration: 0.5s;
animation-name: background-close;
animation-fill-mode: both;
animation-delay: 0s;
}
}
.__up_pop {
position: fixed;
border-radius: 8px;
left: 50%;
top: 50%;
transform: translateX(-50%);
z-index: 999999;
background-color: @backgoundColor;
background-repeat: no-repeat;
box-shadow: 0px 0px 8px 0px #00000040;
@keyframes open-pop {
0% {
opacity: 0;
transform: translate(-50%, -50%) scale(0);
}
100% {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
}
@keyframes close-pop {
0% {
opacity: 1;
transform: translate(-50%, -50%) scale(1);
}
100% {
opacity: 0;
transform: translate(-50%, -50%) scale(0);
}
}
&.__up_visible {
animation-duration: 0.5s;
animation-name: open-pop;
animation-fill-mode: both;
animation-delay: 0s;
}
&.__up_hidden {
opacity: 0;
}
&.__up_hide {
animation-duration: 0.3s;
animation-name: close-pop;
animation-fill-mode: both;
animation-delay: 0s;
}
.__up_close_icon {
position: absolute;
top: 16px;
right: 16px;
cursor: pointer;
width: 24px;
height: 24px;
background-color: transparent;
svg {
fill: @textColor;
}
}
.__up_pop_content {
padding: 80px 220px;
.__up_header_text {
font-family: @font-family;
color: @textColor;
font-size: 25px;
line-height: 36px;
text-align: center;
letter-spacing: normal;
word-break: normal;
font-weight: 200;
margin: 0 0 16px;
}
.__up_headline_text {
font-family: @font-family-bold;
color: @headingColor;
font-weight: 700;
font-size: 100px;
line-height: 100px;
letter-spacing: normal;
word-break: normal;
text-align: center;
white-space: nowrap;
margin: 0 0 16px;
}
.__up_underline_text {
.__up_header_text();
margin: 0 0 80px;
}
.__up_action {
position: relative;
border-radius: 8px;
margin: 0 5px 24px;
.__up_show_button {
position: absolute;
z-index: 2;
cursor: pointer;
display: block;
padding: 16px 32px;
background-color: @buttonColor;
background: @buttonColor;
color: @buttonFontColor;
font-family: @font-family;
font-weight: 500;
font-size: 25px;
line-height: 25px;
letter-spacing: normal;
word-break: normal;
text-align: center;
text-transform: uppercase;
border: none;
border-radius: 8px;
transition: background-color 300ms linear;
box-shadow: 0px 3px 3px 0px #00000029;
height: 82px;
box-sizing: border-box;
left: 0;
right: 0;
&:hover {
background-color: @buttonHoverColor;
}
&:focus {
background-color: @buttonFocusColor;
}
&.__up_hidden {
display: none;
}
}
.__up_code_wrapper {
display: flex;
flex-direction: row;
justify-content: center;
width: auto;
gap: 8px;
.__up_code_value {
border: none;
outline: none;
box-shadow: none;
border-radius: 8px;
font-family: @font-family;
background-color: @inputColor;
color: @textColor;
transition: all 300ms linear;
font-size: 24px;
line-height: 24px;
font-weight: 400;
letter-spacing: normal;
word-break: normal;
text-align: center;
flex: 1;
min-width: 400px;
padding: 0 16px;
&.__up_code_input_copied {
background-color: @buttonColor;
color: @buttonFontColor;
}
}
.__up_code_value_input_label{
visibility: hidden;
width: 0;
}
.__up_action_button {
cursor: pointer;
padding: 16px 32px;
background-color: @buttonColor;
font-family: @font-family;
color: @buttonFontColor;
font-weight: 500;
font-size: 25px;
line-height: 25px;
letter-spacing: normal;
word-break: normal;
text-align: center;
text-transform: uppercase;
border: none;
border-radius: 8px;
box-shadow: 0px 3px 3px 0px #00000029;
transition: background-color 300ms linear;
width: min-content;
&:hover {
background-color: @buttonHoverColor;
}
&:focus {
background-color: @buttonFocusColor;
}
}
&.__up_visible {
opacity: 1;
}
&.__up_hidden {
opacity: 0;
}
}
}
.__up_dismiss {
cursor: pointer;
font-size: 20px;
line-height: 20px;
font-family: @font-family;
letter-spacing: normal;
word-break: normal;
color: @buttonColor;
font-weight: 300;
text-align: center;
text-decoration: underline;
margin: 0 0 16px;
}
.__up_footer {
font-size: 14px;
line-height: 14px;
font-family: @font-family;
color: @textColor;
letter-spacing: normal;
word-break: normal;
font-weight: 400;
text-align: center;
}
}
}
}//Custom Condition
if(document.referrer.includes("https://www.bundeswehr-und-mehr.de")) {
return false;
}
const KEY = "__up_pop_block_cleanup_executed";
const TTL = 24 * 60 * 60 * 1000; // 24 hours
const stored = localStorage.getItem(KEY);
if (stored) {
const timestamp = Number(stored);
if (Date.now() - timestamp < TTL) {
return false;
}
localStorage.removeItem(KEY);
}
return true;// User Closes Popup Tracking Code
const KEY = "__up_pop_block_cleanup_executed";
localStorage.removeItem("*__up_pop_block");
localStorage.removeItem("3__up_pop_block");
return true;//Popup is displayed Tracking Code
const KEY = "__up_pop_block_cleanup_executed";
localStorage.setItem(KEY, Date.now());