Optimove ยท Email + Popup

Welcome Pack โ€” Pick One

A plain-English guide to the updated welcome pack flow: popup shown once, offer also delivered via email, one campaign in Optimove.

What this campaign does

When a new player registers, they see a popup showing three welcome offers โ€” once and only once. If they close it without choosing, the same three links are in their welcome email. Whichever they click, the site records the selection and Optimove awards the right bonus.

This is an example setup, not a fixed spec. The offers, Package IDs, and audience rules shown here illustrate one way to build this campaign. The actual configuration can be changed to fit your requirements.
๐Ÿ†•
Who sees it
New players immediately after signup. The popup fires exactly once โ€” if dismissed, offer links are in the welcome email instead.
๐ŸŽ
Three offers
100% Deposit Bonus, 50 Free Spins, or 200% VIP Bonus. The player picks exactly one. All three remain visible in the cashier until one is purchased.
๐Ÿ”—
Popup once, email backup
Player dismisses popup โ†’ no problem. The email has the same three offer links. Clicking any link lands them back on the site with the selection pre-set.
No auto-award fallback in this flow. Players who never click any offer simply don't receive a welcome bonus. An auto-award fallback (e.g. award smallest pack after 24 h of inactivity) is a valid alternative path โ€” it can be layered on top as a separate Campaign 3 using uncompleted_sequence_1 if the business wants it.

How it works, step by step

Four things happen in sequence from signup to bonus award.

1

Popup + email on signup

Player registers. Optimove sends a welcome email on sign_up and shows the popup on sign_up โ†’ page_visit within 15 min. The popup requires page_visit because Optimove can only display popups on a live FE page event โ€” the email fires immediately on registration without waiting for a page load.

โ†’
2

Player clicks an offer

Clicking any offer โ€” in the popup or in the email โ€” opens the site at moonspin.us?selected-offer-award-id=<id>&selected-offer-promo-id=<promoId>. Both the award and the promo identifier are embedded in the URL.

โ†’
3

Site fires the event

The site reads the URL param. Once the player is authenticated it calls the BE, which sends a promo_award_selected event to Optimove with award_id and promo_id.

โ†’
4

Optimove triggers campaign

The single real-time trigger fires (filter: award_id IN (โ€ฆ) AND promo_id = 'โ€ฆ', once per lifetime). BE receives the callback, reads award_id from the event, and awards the selected pack.

Ad-blocker safe. The event is sent server-to-server by the backend โ€” not by the Optimove browser SDK. A player with an ad-blocker will still have their selection recorded correctly.
Popup closed without choosing? No problem. The email links work exactly the same way. The site processes ?selected-offer-award-id= + ?selected-offer-promo-id= from any entry point โ€” popup redirect, email click, or direct URL share.

The three welcome offers

Each offer has a Package ID โ€” the SwPackage UUID used in the URL param, the Optimove trigger filter, and the BE award logic. You'll need all three IDs when configuring the trigger and the email links.

๐Ÿ’ฐ
100% Deposit Bonus โ€” matches the player's deposit, up to $200
Package ID
a8822f1a-67d4-4110-be4a-17be0d3480db
๐ŸŽฐ
50 Free Spins โ€” no wagering required on winnings
Package ID
0a1ed776-e408-4edf-9f2b-e17d9e6c21a5
๐Ÿ‘‘
200% VIP Bonus โ€” up to $1,000 + priority support
Package ID
d1fde953-1ed4-4018-a3ba-1f0a9a7defa9

Setting up the campaign in Optimove

Three things to configure: the popup campaign, the welcome email, and one real-time trigger + campaign pair. Much simpler than the previous three-trigger setup.

1

Campaign 1 โ€” show the popup once to new players

Create a campaign that shows the welcome pack popup on the player's first page visit after signing up. In the campaign's popup step, paste the popup HTML from the bottom of this page.

The trigger requires page_visit because Optimove can only display a popup on a live FE page event โ€” there is no way to show a popup without an active browser session. The email (step 2) fires on sign_up alone and does not need a page event.

Trigger: sign_up โ†’ page_visit within 15 minutes, once per lifetime

This campaign only shows the popup. The award is handled by Campaign 2 when the player selects an offer.
2

Welcome email โ€” three offer links

Create a welcome email in Optimove triggered by sign_up alone โ€” no page_visit needed. The email fires immediately on registration, before the player even returns to the site. Each button links to the site with the award ID and promo ID pre-set in the URL. If the player dismissed the popup without choosing, the email is their second chance.

100% Deposit Bonus link:
https://moonspin.us/en?selected-offer-award-id=a8822f1a-67d4-4110-be4a-17be0d3480db&selected-offer-promo-id=welcome_pack_v1

50 Free Spins link:
https://moonspin.us/en?selected-offer-award-id=0a1ed776-e408-4edf-9f2b-e17d9e6c21a5&selected-offer-promo-id=welcome_pack_v1

200% VIP Bonus link:
https://moonspin.us/en?selected-offer-award-id=d1fde953-1ed4-4018-a3ba-1f0a9a7defa9&selected-offer-promo-id=welcome_pack_v1
Push notifications can use the same URL links. Note: deep-linking from in-app notifications into the cashier is not yet supported โ€” the link will land on the home page and the site will pick up the param from there.
3

One real-time trigger โ€” promo_award_selected

In Optimove, go to Triggers โ†’ Real-Time. Create a single trigger that listens for the promo_award_selected event. Add two filters: award_id scopes it to the three welcome pack award UUIDs; promo_id scopes it to this specific promo campaign so other future uses of promo_award_selected don't accidentally fire this trigger. Set it to fire once per lifetime per player.

Trigger: promo_award_selected event fires
Filter: award_id IN (a8822f1a-..., 0a1ed776-..., d1fde953-...)
          AND promo_id = 'welcome_pack_v1'
Frequency: once per lifetime

The event is sent server-to-server by the backend when the player lands on the site with valid ?selected-offer-award-id= and ?selected-offer-promo-id= params and is authenticated. The trigger reads award_id from the event payload so the backend knows which award to give on callback.

4

Campaign 2 โ€” award the selected package

Create one campaign triggered by the real-time trigger above. The backend reads package_id from the event's personalization data in the Optimove callback and awards exactly that SwPackage. No branching needed โ€” a single campaign handles all three offers.

Triggered by: the real-time trigger from step 3

The campaign does not need separate promo codes or branches per offer. The backend reads award_id from the event's personalization data in the Optimove callback and awards exactly that pack.
5

(Optional) Campaign 3 โ€” auto-award fallback

If the business wants every player to receive a welcome bonus regardless of whether they pick one, add a fallback campaign. Set up a sequential event (uncompleted_sequence_1) that fires when sign_up occurs but promo_award_selected does not occur within a defined window (e.g. 24 h). Campaign 3 then auto-awards the fallback bonus.

This step is optional. The primary flow does not include an auto-award. Add it only if the business explicitly requires guaranteed bonus delivery for every registrant.
6

Test before going live

Use Optimove's test mode with a test player. Click each offer in the popup and verify the URL redirects correctly with the right ?selected-offer-award-id= and ?selected-offer-promo-id= values. Check the Optimove event stream to confirm promo_award_selected arrives with the correct award_id and promo_id. Verify Campaign 2 fires and the right SwPackage is awarded.

Known quirks in Optimove's popup editor

If a developer is modifying the popup HTML, these are the limitations to watch for. The popup code below is already written to work around all of them.

No // single-line comments inside scripts

Optimove's editor strips newlines from script blocks. A // comment would comment out all remaining code on that line. Use /* */ block comments instead, or no comments at all.

No ?. optional chaining

The editor inserts a space turning ?. into ? ., which breaks JavaScript syntax and silently kills the entire script. Use && guards instead.

No inline onclick attributes

The site's security policy blocks inline event handlers. Use addEventListener inside the <script> block โ€” it works because the script tag itself receives the security nonce.

Use event delegation, not per-element listeners

Attach click handlers to document and use e.target.closest(). Optimove may re-render the popup DOM after images load, which destroys listeners attached directly to elements.

Popup HTML

The block below is an example popup for the welcome pack. You can build your own โ€” the design and layout can be anything. The only requirement is that the script fires the right event when a player makes a selection.

How the popup script works

The popup no longer calls optimoveSDK.API.reportEvent() directly. Instead, clicking an offer navigates the player to the site with ?selected-offer-award-id= and selected-offer-promo-id= URL params. The site reads both params, calls the backend, and the backend sends the promo_award_selected event to Optimove server-to-server. This approach is ad-blocker safe.

1๏ธโƒฃ
data-award-id โ€” set on each offer element. The UUID of the award for that offer (see Package IDs above). The script reads this and sets selected-offer-award-id in the URL.
2๏ธโƒฃ
URL redirect โ€” the script builds a URL from window.location.href and sets selected-offer-award-id + selected-offer-promo-id, then navigates there after a brief confirmation flash.
3๏ธโƒฃ
No SDK dependency โ€” the script does not call window.optimoveSDK at all. Works even if the SDK is blocked by an ad-blocker.
Popup shown only once. Campaign 1 is configured once per lifetime. If the player dismisses without selecting, they can still choose an offer via the welcome email links โ€” the same URL param mechanism applies.

Example popup code

Paste into Optimove popup code editor HTML
<!DOCTYPE html>
<html>
	<head>
		<title>Optimove Welcome Pack</title>
	</head>
	<body>
		<div class="bee-popup-container">
			<style>
				.bee-popup-container h1,
				.bee-popup-container h2,
				.bee-popup-container p {
					margin: 0;
					padding: 0;
				}
				.bee-popup-container {
					color: #ffffff;
					font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
					background-color: #000000;
				}
				.bee-popup-container * {
					box-sizing: border-box;
				}
				.bee-popup-row {
					position: relative;
				}
				.bee-popup-row-content {
					max-width: 700px;
					position: relative;
					margin: 0 auto;
					display: flex;
				}
				.bee-popup-col-w4 {
					flex: 4;
				}
				.bee-popup-col-w12 {
					flex: 12;
				}
				.bee-popup-row-1 .bee-popup-row-content {
					flex-direction: column;
					align-items: center;
					padding: 32px 24px 16px;
					gap: 8px;
				}
				.bee-popup-eyebrow {
					font-size: 11px;
					font-weight: 700;
					letter-spacing: 0.18em;
					text-transform: uppercase;
					color: #13e3ba;
					opacity: 0.8;
				}
				.bee-popup-heading h1 {
					color: #ffffff;
					font-size: 30px;
					font-weight: 800;
					letter-spacing: -0.01em;
					text-align: center;
					line-height: 1.15;
				}
				.bee-popup-heading h1 span {
					color: #13e3ba;
				}
				.bee-popup-subheading {
					font-size: 13px;
					color: rgba(255, 255, 255, 0.45);
					text-align: center;
					margin-top: 4px;
				}
				.bee-popup-row-2 .bee-popup-row-content {
					padding: 16px 24px 36px;
					gap: 12px;
					align-items: stretch;
				}
				.bee-popup-offer {
					position: relative;
					background: linear-gradient(160deg, #161616 0%, #0e0e0e 100%);
					border: 1.5px solid #2a2a2a;
					border-radius: 16px;
					text-align: center;
					cursor: pointer;
					display: flex;
					flex-direction: column;
					align-items: center;
					transition: border-color 0.2s ease, transform 0.15s ease, box-shadow 0.2s ease;
					overflow: hidden;
				}
				.bee-popup-offer::before {
					content: "";
					position: absolute;
					inset: 0;
					background: radial-gradient(ellipse at 50% 0%, rgba(19, 227, 186, 0.08) 0%, transparent 70%);
					opacity: 0;
					transition: opacity 0.2s ease;
					pointer-events: none;
					z-index: 1;
				}
				.bee-popup-offer:hover {
					border-color: #13e3ba;
					transform: translateY(-3px);
					box-shadow: 0 8px 28px rgba(19, 227, 186, 0.15);
				}
				.bee-popup-offer:hover::before {
					opacity: 1;
				}
				.bee-popup-offer:active {
					transform: translateY(-1px);
				}
				.offer-banner {
					width: 100%;
					display: block;
					border-radius: 14px 14px 0 0;
					object-fit: cover;
					aspect-ratio: 7 / 3;
					background-color: #1a1a1a;
				}
				.offer-body {
					display: flex;
					flex-direction: column;
					align-items: center;
					gap: 6px;
					padding: 14px 14px 18px;
					width: 100%;
				}
				.offer-highlight {
					font-size: 28px;
					font-weight: 800;
					color: #13e3ba;
					letter-spacing: -0.02em;
					line-height: 1;
				}
				.offer-label {
					font-size: 11px;
					font-weight: 700;
					letter-spacing: 0.12em;
					text-transform: uppercase;
					color: rgba(255, 255, 255, 0.55);
					margin-top: 2px;
				}
				.offer-divider {
					width: 28px;
					height: 1px;
					background: rgba(19, 227, 186, 0.25);
					margin: 4px auto;
				}
				.offer-description {
					font-size: 11px;
					color: rgba(255, 255, 255, 0.35);
					line-height: 1.4;
				}
				.offer-badge {
					position: absolute;
					top: -1px;
					right: -1px;
					background: #13e3ba;
					color: #000000;
					font-size: 9px;
					font-weight: 800;
					letter-spacing: 0.1em;
					text-transform: uppercase;
					padding: 3px 8px;
					border-radius: 0 14px 0 8px;
					z-index: 2;
				}
				.bee-popup-row-divider {
					height: 1px;
					background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.06) 30%, rgba(255, 255, 255, 0.06) 70%, transparent);
					max-width: 700px;
					margin: 0 auto;
				}
			</style>
			<div id="opt-before-select" class="bee-popup-rows-container">
				<div class="bee-popup-row bee-popup-row-1">
					<div class="bee-popup-row-content">
						<div class="bee-popup-eyebrow">New Player Offer</div>
						<div class="bee-popup-col bee-popup-col-w12">
							<div class="bee-popup-heading">
								<h1>CHOOSE YOUR <span>WELCOME PACK</span></h1>
							</div>
						</div>
						<div class="bee-popup-subheading">Pick one offer to claim on your first deposit</div>
					</div>
				</div>
				<div class="bee-popup-row-divider"></div>
				<div class="bee-popup-row bee-popup-row-2">
					<div class="bee-popup-row-content">
						<div class="bee-popup-col bee-popup-col-w4">
							<div class="bee-popup-offer" data-award-id="a8822f1a-67d4-4110-be4a-17be0d3480db" data-promo-id="welcome_pack_v1">
								<picture>
									<source media="(min-width: 480px)" srcset="https://swivel-production-public.s3.eu-west-1.amazonaws.com/sw-packages/7a801a29-c686-4a5a-b533-2d3075e164ca.largeImage">
									<img class="offer-banner" src="https://swivel-production-public.s3.eu-west-1.amazonaws.com/sw-packages/1f1f56c2-20f5-4301-aa89-38c3b00922ba.smallImage" alt="Starter Pack">
								</picture>
								<div class="offer-body">
									<div class="offer-highlight">100%</div>
									<div class="offer-label">Deposit Bonus</div>
									<div class="offer-divider"></div>
									<div class="offer-description">Up to $200
										<br>matched bonus</div>
								</div>
							</div>
						</div>
						<div class="bee-popup-col bee-popup-col-w4">
							<div class="bee-popup-offer" data-award-id="0a1ed776-e408-4edf-9f2b-e17d9e6c21a5" data-promo-id="welcome_pack_v1">
								<div class="offer-badge">Popular</div>
								<picture>
									<source media="(min-width: 480px)" srcset="https://swivel-production-public.s3.eu-west-1.amazonaws.com/sw-packages/bef4de2e-337e-41ca-83f3-3adb02e24c29.smallImage">
									<img class="offer-banner" src="https://swivel-production-public.s3.eu-west-1.amazonaws.com/sw-packages/bef4de2e-337e-41ca-83f3-3adb02e24c29.smallImage" alt="Free Spins Pack">
								</picture>
								<div class="offer-body">
									<div class="offer-highlight">50</div>
									<div class="offer-label">Free Spins</div>
									<div class="offer-divider"></div>
									<div class="offer-description">No wagering
										<br>on winnings</div>
								</div>
							</div>
						</div>
						<div class="bee-popup-col bee-popup-col-w4">
							<div class="bee-popup-offer" data-award-id="d1fde953-1ed4-4018-a3ba-1f0a9a7defa9" data-promo-id="welcome_pack_v1">
								<picture>
									<source media="(min-width: 480px)" srcset="https://swivel-production-public.s3.eu-west-1.amazonaws.com/sw-packages/99ba733e-6f85-4861-9984-6c7beb27a5bc.largeImage">
									<img class="offer-banner" src="https://d3aaoo30se75mz.cloudfront.net/1712/2026_05_26_9_00_33/smallImg.png" alt="VIP Pack">
								</picture>
								<div class="offer-body">
									<div class="offer-highlight">200%</div>
									<div class="offer-label">VIP Bonus</div>
									<div class="offer-divider"></div>
									<div class="offer-description">Up to $1000
										<br>+ priority support</div>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
			<div id="opt-after-select" style="display:none; padding:48px 24px; text-align:center; background:#000;">
				<div style="font-size:36px; margin-bottom:12px;">โœ“</div>
				<div style="font-size:18px; font-weight:800; color:#13e3ba;">Offer selected</div>
				<div style="font-size:13px; color:rgba(255,255,255,0.45); margin-top:8px;">Head to the coin store and buy it.</div>
			</div>
		</div>
		<script>
			console.debug("Popup Open");
			document.addEventListener("click", function(e)
			{
				var offer = e.target.closest(".bee-popup-offer[data-award-id]");
				if (!offer)
				{
					return;
				}
				var awardId = offer.getAttribute("data-award-id");
				var promoId = offer.getAttribute("data-promo-id");
				var url = new URL(window.location.href);
				url.searchParams.set("selected-offer-award-id", awardId);
				url.searchParams.set("selected-offer-promo-id", promoId);
				document.getElementById("opt-before-select").style.display = "none";
				document.getElementById("opt-after-select").style.display = "block";
				setTimeout(function()
				{
					window.location.href = url.toString();
				}, 1500);
			});
		</script>
	</body>
</html>