Pawsome Birthday Club

Back to Home

A personalized monthly Birthday Campaign for Pawsome Pet Co., built to demonstrate AMPscript-first email development using Data Extensions, dynamic content, personalized offers, pet-based recommendations, MJML and responsive HTML email.

AMPscript Data Extensions Dynamic Content Personalization MJML HTML Email Remove.bg

Email Preview

Project Overview

Pawsome Pet Co. runs a monthly Birthday Club campaign for customers whose pets have birthdays during the current month. This campaign combines a personalized birthday message, customer-specific discount, loyalty-tier messaging and two pet-relevant gift recommendations. The campaign is designed as an AMPscript-heavy SFMC email rather than a static HTML creative.

Objective

Build a Monthly Birthday Club email that feels personal and brand-led while demonstrating practical AMPscript skills. The supplied Birthday Club DE acts as the send audience, while lookup Data Extensions provide reusable pet personality content and gift recommendations.

Campaign Flow

Birthday Club DE
       ↓
Subscriber + Pet Attributes
       ↓
AMPscript
       β”œβ”€β”€ First Name fallback
       β”œβ”€β”€ Pet Personality lookup
       β”œβ”€β”€ Loyalty-tier subject line
       β”œβ”€β”€ Gift recommendation lookup
       β”œβ”€β”€ Discount calculation
       └── Pet-type banner selection
       ↓
Personalized MJML / HTML Email
       ↓
September Birthday Club Send

The provided send audience already contains customers with September pet birthdays, so no SQL audience-selection step is required for this campaign. AMPscript performs the runtime content assembly and personalization inside the email.

Data Model

Birthday Club

SubscriberKey
FirstName
EmailAddress
PetName
PetType
Breed
PetBirthday
DiscountCode
DiscountPercent
LoyaltyTier

Pet Personality

PetType
BirthdayHeadline
BirthdayPersonality
PetDescription
PetEmoji

Gift Ideas

GiftID
GiftName
PetType
Category
Price
Description
ShopURL
ImageURL
Birthday Club
     β”‚
     β”œβ”€β”€ PetType ──────────→ Pet Personality
     β”‚
     └── PetType ──────────→ Gift Ideas
                              ↓
                       2 Recommendations

AMPscript

AMPscript is the primary orchestration layer. It reads the sendable subscriber attributes, retrieves reusable content from the lookup Data Extensions, builds the personalized subject line, calculates recommendation prices after the birthday discount and selects the appropriate hero image.

%%[
var @subscriberKey, @firstName, @emailAddress, @petName, @petType, @discountPercent, @loyaltyTier

SET @subscriberKey = AttributeValue("SubscriberKey")
SET @firstName = AttributeValue("FirstName")
SET @emailAddress = AttributeValue("EmailAddress")
SET @petName = AttributeValue("PetName")
SET @petType = AttributeValue("PetType")
SET @discountPercent = AttributeValue("DiscountPercent")
SET @loyaltyTier = AttributeValue("LoyaltyTier")
SET @date = SystemDateToLocalDate(Now(1))
SET @offerMonth = FormatDate(@date, 'MMMM')
SET @offerValidity = FormatDate(@date, 'Y')

/*Validate firstName*/
IF EMPTY(@firstName) THEN
	SET @firstName = 'there'
ENDIF

/*Content(personality) based on pet type*/
SET @petPersonalityRows = LookupRows('Pet Personality', 'PetType', @petType)
IF rowCount(@petPersonalityRows) > 0 THEN
	VAR @row, @birthdayHeadline, @birthdayPersonality, @petDescription
	SET @row = Row(@petPersonalityRows, 1)
	SET @birthdayHeadline = Field(@row, 'BirthdayHeadline')
	SET @birthdayPersonality = Field(@row, 'BirthdayPersonality')
	SET @petDescription = Field(@row, 'PetDescription')
	SET @petEmoji = Field(@row, 'petEmoji')
ENDIF

/*Dynamic subjectline based on loyalty tier*/
IF @loyaltyTier == 'Platinum' THEN
	SET @subjectline = Concat('A VIP birthday treat, just for ', @petName, ' ', @petEmoji)
ELSEIF @loyaltyTier == 'Gold' THEN
	SET @subjectline = Concat('Celebrate ', @petName,' with a birthday treat from us ', @petEmoji)
ELSEIF @loyaltyTier == 'Silver' THEN
	SET @subjectline = Concat("Extra cuddles. Extra treats. It's ", @petName, "'s birthday! ", @petEmoji)
ELSE
	SET @subjectline = Concat("It's paw-ty time ", @petName, "! Your birthday treat is waiting ", @petEmoji)
ENDIF

/*Get 2 gift recommendations*/
SET @giftIdeasRows = LookupOrderedRows('Gift Ideas', 2, 'Price DESC', 'PetType', @petType)
SET @giftIdeasCount = rowCount(@giftIdeasRows)
SET @giftRow1 = Row(@giftIdeasRows, 1)
SET @giftName1 = Field(@giftRow1, 'GiftName')
SET @giftPrice1 = Field(@giftRow1, 'Price')
SET @formatGiftPrice1 = FormatNumber(@giftPrice1, "C")
SET @finalPrice1 = FormatNumber(Subtract(@giftPrice1, Multiply(@giftPrice1, Divide(@discountPercent, 100))), "C")
SET @giftDescription1 = Field(@giftRow1, 'Description')
SET @shopURL1 = Field(@giftRow1, 'ShopURL')
SET @imageURL1 = Field(@giftRow1, 'ImageURL')

IF @giftIdeasCount == 2 THEN
	SET @giftRow2 = Row(@giftIdeasRows, 2)
	SET @giftName2 = Field(@giftRow2, 'GiftName')
	SET @giftPrice2 = Field(@giftRow2, 'Price')
	SET @formatGiftPrice2 = FormatNumber(@giftPrice2, "C")
	SET @finalPrice2 = FormatNumber(Subtract(@giftPrice2, Multiply(@giftPrice2, Divide(@discountPercent, 100))), "C")
	SET @giftDescription2 = Field(@giftRow2, 'Description')
	SET @shopURL2 = Field(@giftRow2, 'ShopURL')
	SET @imageURL2 = Field(@giftRow2, 'ImageURL')
ELSE
	SET @giftIdeasRowsAll = LookupOrderedRows('Gift Ideas', 1, 'Price DESC', 'PetType', 'All')
	SET @giftRow2 = Row(@giftIdeasRowsAll, 1)
	SET @giftName2 = Field(@giftRow2, 'GiftName')
	SET @giftPrice2 = Field(@giftRow2, 'Price')
	SET @formatGiftPrice2 = FormatNumber(@giftPrice2, "C")
	SET @finalPrice2 = FormatNumber(Subtract(@giftPrice2, Multiply(@giftPrice2, Divide(@discountPercent, 100))), "C")
	SET @giftDescription2 = Field(@giftRow2, 'Description')
	SET @shopURL2 = Field(@giftRow2, 'ShopURL')
	SET @imageURL2 = Field(@giftRow2, 'ImageURL')
ENDIF

/*Dynamic banner based on pet type*/
IF @petType == 'Dog' THEN
	SET @banner = 'https://as1.ftcdn.net/v2/jpg/03/22/78/92/1000_F_322789275_pRYGzHcwPOBFiSD34xXIMILVMGxfqJBV.jpg'
ELSE
	SET @banner = 'https://images.ampscriptacademy.com.au/uploads/hero-gemini-removebg-preview.png'
ENDIF
]%%

Dynamic Content & Personalization

Pet Personalization PetName is used throughout the birthday experience and CTA copy.
Optional First Name FirstName is checked and falls back to β€œthere” when the source value is empty.
Pet Personality Headline, personality copy and emoji are retrieved from the Pet Personality DE by PetType.
Loyalty-Tier Subject Platinum, Gold, Silver and Bronze/default customers receive different subject-line treatments.
Personalized Offer Discount percentage and unique DiscountCode are read directly from the send audience.
September Validity The offer is presented as valid throughout the campaign month rather than calculating a daily expiry date.
Pet-Based Recommendations Up to two gift records are selected using PetType and ordered by price.
Recommendation Fallback If only one pet-specific gift exists, an β€œAll” gift fills the second recommendation slot.
Dynamic Pricing Recommendation prices show the original price and the customer-specific discounted price.
Dynamic Hero Banner The banner image changes based on the subscriber’s PetType.

MJML

MJML is used for the responsive email structure. AMPscript variables are embedded directly into the MJML so the compiled HTML retains the dynamic SFMC logic.

<mjml>
	<mj-head>
		<mj-attributes>
			<mj-all font-size="16px" font-family="Helvetica, Arial, sans-serif" color="#333333" line-height="22px" /> </mj-attributes>
	</mj-head>
	<mj-body background-color="#d6dde5">
		<mj-section background-color="#fa8739">
			<mj-column>
				<mj-text align="center" font-weight="800" font-family="Comic Sans Ms">Pawsome Pet Co.</mj-text>
			</mj-column>
		</mj-section>
		<mj-section padding="0px">
			<mj-column padding="0px">
				<mj-image padding="0px" src="%%=v(@banner)=%%"></mj-image>
			</mj-column>
		</mj-section>
		<mj-section background-color="#fff">
			<mj-column>
				<mj-text align="center" font-size="20px" line-height="26px" font-family="Comic Sans Ms">
					<p>%%=v(@birthdayHeadline)=%%</p>
					<p>%%=v(@offerMonth)=%% is %%=v(@petName)=%%'s Birthday Month! %%=v(@petEmoji)=%%</p>
					<p>%%=v(@birthdayPersonality)=%%</p>
				</mj-text>
				<mj-divider border-width="1px" border-style="dashed" border-color="lightgrey" />
				<mj-text font-family="Helvetica" font-size="14px">
					<p>Hey %%=v(@firstName)=%%,</p>
					<p>Someone special is celebrating another trip around the sun!</p>
					<p>To make the celebration even more pawsome, enjoy <strong>%%=v(@discountPercent)=%% OFF</strong> on your next purchase.</p>
					<p>Use your personal birthday code: <span style="font-family:Comic Sans Ms; background:#fa8739">%%=v(@discountCode)=%%</span></p>
					<p style="font-family:Comic Sans Ms">Valid throughout %%=v(@offerValidity)=%%.</p>
				</mj-text>
				<mj-button background-color="#fa8739" color="#fff" border-radius="20px">Claim %%=v(@petName)=%%'s Birthday</mj-button>
			</mj-column>
		</mj-section>
		<mj-section background-color="#fa8739" padding-bottom="0px" padding-top="0">
			<mj-column background-color="#fa8739">
				<mj-image src="%%=v(@imageURL1)=%%" alt="giftImage1" width="301px" padding-left="0px" padding-right="0px" padding-bottom="0px" padding-top="0"></mj-image>
			</mj-column>
			<mj-column width="50%">
				<mj-text align="left" color="#fff" font-size="13px" padding-left="25px" padding-right="25px" padding-bottom="0px" padding-top="0">
					<p style="font-size: 19px;">%%=v(@giftName1)=%%</p>
					<p style="font-size: 36px;"><s style="font-size: 26px; color:#d6dde5">%%=v(@formatGiftPrice1)=%%</s> %%=v(@finalPrice1)=%%</p>
					<p>%%=v(@giftDescription1)=%%</p>
				</mj-text>
				<mj-button background-color="#fff" color="#fa8739" padding="15px 30px" border-radius="3px" href="%%=v(@shopURL1)=%%" padding-bottom="10px" padding-top="0">BUY NOW</mj-button>
			</mj-column>
		</mj-section>
		<mj-section background-color="#2f323b" padding-bottom="0px" padding-top="0">
			<mj-column>
				<mj-text align="left" color="#fff" font-size="13px" padding-left="25px" padding-right="25px" padding-bottom="0px" padding-top="0">
					<p style="font-size: 19px;">%%=v(@giftName2)=%%</p>
					<p style="font-size: 36px;"><s style="font-size: 26px; color:#d6dde5">%%=v(@formatGiftPrice2)=%%</s> %%=v(@finalPrice2)=%%</p>
					<p>%%=v(@giftDescription2)=%%</p>
				</mj-text>
				<mj-button background-color="#fa8739" color="#fff" padding="15px 30px" border-radius="3px" href="%%=v(@shopURL2)=%%" padding-bottom="10px" padding-top="0">BUY NOW</mj-button>
			</mj-column>
			<mj-column>
				<mj-image src="%%=v(@imageURL2)=%%" alt="giftImage2" align="center" border="none" width="302px" padding-left="0px" padding-right="0px" padding-bottom="0px" padding-top="0"></mj-image>
			</mj-column>
		</mj-section>
		<mj-section background-color="#fff" padding-bottom="1px" padding-top="0px"></mj-section>
		<mj-section padding="0px" background-color="#fa8739">
			<mj-column padding="0px">
				<mj-text align="center" line-height="20px">
					<p>Here's to another year of happy tails, tiny paws, big personalities and plenty of treats. 🐾</p>
					<p>Happy Birthday, %%=v(@petName)=%%!</p>
					<p>Β© The Pawsome Pet Co. Team</p>
					<p style="font-size:12px"><a href="#" style="color: inherit;">Manage Preferences</a> | <a href="#" style="color: inherit;">Unsubscribe</a></p>
				</mj-text>
			</mj-column>
		</mj-section>
		<mj-section padding="0px" background-color="#fa8739">
			<mj-column padding="0px 0px 20px 0px">
				<mj-social>
					<mj-social-element name="facebook" href="#"></mj-social-element>
					<mj-social-element name="twitter" href="#"></mj-social-element>
					<mj-social-element name="instagram" href="#"></mj-social-element>
				</mj-social>
			</mj-column>
		</mj-section>
	</mj-body>
</mjml>

Implementation Notes

The campaign intentionally keeps the creative structure simple: one birthday hero/message area, one personalized offer and two recommendation sections with alternating layouts. This keeps the email visually engaging while leaving AMPscript as the primary technical focus.

The Gift Ideas lookup uses two pet-specific records when available. If only one exists, the first recommendation remains pet-specific and the second is populated from a generic β€œAll” record. The email therefore maintains its two-product layout without hard-coding product content into the HTML.

Key Features

AMPscript-First Architecture Business and personalization logic is handled in AMPscript rather than hard-coded into the creative.
Multiple DE Lookups Subscriber data drives lookups into Pet Personality and Gift Ideas.
Conditional Logic First-name fallback, loyalty-tier subject logic and gift fallback logic are handled at send time.
Dynamic Product Content Gift name, description, original price, discounted price, image and URL are data-driven.
Reusable Content Model Pet personality and gift content live in lookup DEs instead of being duplicated in the email.
Responsive Email Email structure is developed in MJML and compiled to responsive HTML.

Source Code

The project includes the AMPscript, MJML source and rendered HTML preview used for the portfolio demonstration.


View Portfolio Repository