Search for products, concerns and keywords.


Your Brand Consultant Agreement has been successfully renewed.
There was a problem processing your Brand Consultant Agreement renewal. Please try again.
There was a system error. Please try again.
There was an issue adding this product. Please refresh the page and try again
You're saving 10% on your entire order, including subscription orders and one-time purchases!

Be a product of the product! Schedule convenient, monthly deliveries of your favorite R+F products at the discounted Consultant price.

Join PC Perks for Free
  • Free gift ($50+ value) with 2nd qualifying order + exclusive offers
  • Fully flexible subscription: Choose delivery frequency and delay or cancel anytime before shipment
Item has been added to your bag.
This field is required.
Home | Total RF Serum
  • Rodan + Fields Total RF Serum

Total RF Serum

$160.00

60 Day Money Back Guarantee

Don't love it? It's on us. Learn More

60 Day Money Back Guarantee

Don't love it? It's on us. Learn More

Our most comprehensive anti-aging serum features RF TriEnergy Complex that energizes millions of surface skin cells by 200% to address all key signs of skin aging.

Recommended Usage: Twice daily, in the AM + PM
Size: 30 mL / 1 Fl. Oz. U.S.

DETAILS

What it is: A powerful anti-aging serum that revitalizes skin to help you see stronger, healthier, more resilient skin. Achieve visible results when using this serum on its own and even better results with a Regimen. Eco-friendly, refillable glass bottle! Keep the outer glass bottle for your refill.

Why you need it: Surface skin cells are compromised by age and environmental factors, losing energy and ability to turnover. Unlock your skin’s potential with our groundbreaking formula for a youthful-looking complexion.

If Total RF Serum is part of a PC Perks enrollment order or added to a PC Perks/CRP replenishment order, the subsequent order will be the Total RF Serum Refill. Preferred Customers and Brand Consultants can change their order at any time before it ships.

Awards: PopSugar Pick 2021 & New Beauty Award 2022

ITEM NUMBER: ENFM030

KEY CONCERNS

Wrinkles, Loss of Firmness, Fine Lines, Uneven Skin Texture + Tone, Dullness, Dry Skin, Enlarged Pores

SKIN TYPE

Suitable for Normal, Dry, Combination, Oily

KEY BENEFITS

Revitalizing face serum helps you see stronger, healthier, more resilient skin

AWARD WINNER

  • Beauty Award Winner

INGREDIENTS

Proprietary Technology + Key Ingredients
  • RF TriEnergy Complex

    Blends Ayurvedic Sandalwood, Indian Kino Extract + Omega-6 Fatty Acid to energize skin
  • Patented RF3 Antioxidant Complex

    Fortifies skin to be more resilient and defensive against environmental aggressors
  • Calcium

    Helps with visible firmness to make skin feel tighter and more resilient
  • Ceramides

    Help fortify skin’s barrier to retain moisture
View All Ingredients
Run out. Refill. Reuse.

Total RF Serum Refill
Keep the serum flowing with a refillable casing + recyclable vial.

$145.00

RESULTS

  • 92%

    had fewer fine lines**
  • 83%

    noticed more refined skin texture**
  • 82%

    instantly had plumper-looking skin*
  • 81%

    had stronger, more resilient skin**
  • 81%

    noticed firmer skin**
  • 75%

    noticed more even looking skin tone**
View Full Study

HOW TO USE

Apply evenly over face AM + PM after cleansing + toning and before moisturizing. For optimal results, allow the serum to dry before moving to next step. Avoid eye area. Formulated to enhance any R+F Regimen.

 

As with any active product we recommend patch testing Total RF Serum before applying it full face using the following instructions:

 

  1. Test 3 X 3 – three times a day for three days
  2. Apply a small amount of the product on your jaw line or neck. Make sure you use the same area each time you test.
  3. Watch for any signs of redness, dryness, irritation, or swelling. If this occurs, do not use the product and contact RF Connection. (rfconnection@rodanandfields.com)
  4. If testing multiple products, apply each product on a separate area for the first day. If no signs of irritation, then patch test by layering the products in the same area as originally applied. Watch for any signs of redness, dryness, irritation, or swelling. If this occurs, do not use the product and contact RF Connection. (rfconnection@rodanandfields.com)
WARNING: Not for children. For external use only. Seek medical attention immediately if ingested or if you experience any irritation or negative reaction.

Use only as directed and after patch-testing, as detailed in the “How to Use” instructions above. If patch-testing results in any sensitivities, immediately discontinue use and contact RF Connection (rfconnection@rodanandfields.com).

If you experience burning, stinging, itching and redness, at any time, even after continued use, immediately discontinue use, seek medical attention, and contact RF Connection (rfconnection@rodanandfields.com). You may also consider consulting your doctor for further advice on potential ingredient sensitivities or interactions with other non-RF products.

 

How to use Total RF Serum with your Regimen:

 

  1. Redefine: after Step 2
  2. Reverse: after Step 2
  3. Soothe: after Step 2
  4. Unblemish: after Step 3
  5. Recharge: after Step 1

HOW TO USE

Apply evenly over face AM + PM after cleansing + toning and before moisturizing. For optimal results, allow the serum to dry before moving to next step. Avoid eye area. Formulated to enhance any R+F Regimen.

 

As with any active product we recommend patch testing Total RF Serum before applying it full face using the following instructions:

 

  1. Test 3 X 3 – three times a day for three days
  2. Apply a small amount of the product on your jaw line or neck. Make sure you use the same area each time you test.
  3. Watch for any signs of redness, dryness, irritation, or swelling. If this occurs, do not use the product and contact RF Connection. (rfconnection@rodanandfields.com)
  4. If testing multiple products, apply each product on a separate area for the first day. If no signs of irritation, then patch test by layering the products in the same area as originally applied. Watch for any signs of redness, dryness, irritation, or swelling. If this occurs, do not use the product and contact RF Connection. (rfconnection@rodanandfields.com)
WARNING: Not for children. For external use only. Seek medical attention immediately if ingested or if you experience any irritation or negative reaction.

Use only as directed and after patch-testing, as detailed in the “How to Use” instructions above. If patch-testing results in any sensitivities, immediately discontinue use and contact RF Connection (rfconnection@rodanandfields.com).

If you experience burning, stinging, itching and redness, at any time, even after continued use, immediately discontinue use, seek medical attention, and contact RF Connection (rfconnection@rodanandfields.com). You may also consider consulting your doctor for further advice on potential ingredient sensitivities or interactions with other non-RF products.

 

How to use Total RF Serum with your Regimen:

 

  1. Redefine: after Step 2
  2. Reverse: after Step 2
  3. Soothe: after Step 2
  4. Unblemish: after Step 3
  5. Recharge: after Step 1

View Less View More

Run out. Refill. Reuse.

Total RF Serum Refill
Keep the serum flowing with a refillable casing + recyclable vial.

$145.00

Reviews

Common questions about the Rodan + Fields

Total RF Serum

What is a serum?

A serum is applied to your skin after cleansing but before moisturizing creams with the intent of introducing powerful ingredients into the skin. Serums are particularly suited to this task because the formula’s lightweight texture blankets skin with a high concentration of key ingredients. This makes them a great tool for targeting specific skincare concerns.

Can the Total RF Serum for anti-aging be used with all regimens?

Yes, Total RF Serum can be used with Redefine, Reverse, Soothe, UNBLEMISH and RECHARGE regimens.

Redefine: use Total RF Serum after Step 2
Reverse: use Total RF Serum after Step 2
Soothe: use Total RF Serum after Step 2
UNBLEMISH: use Total RF Serum after Step 3
RECHARGE: use Total RF Serum after Step 1

As with any new product, we recommend users with sensitive skin to patch test the Total RF Serum before applying it to their face.

Although Total RF Serum was formulated to enhance any R+F Regimen, it does not need to be used with a R+F Regimen to address anti-aging skin concerns. The serum does not need to be used with the R+F Regimen to get results, but you’ll get better results with a Regimen.

Can I layer face serums, and in what order?

While you could choose to only use one serum based on your primary targeted need, you can layer two serums or more and still benefit from their targeted results. If layering with other Serums, the application order is Active Hydration Serum, Intensive Renewing Serum and then Total RF Serum.

Can I use the refill without the full-size Total RF Serum?

You need to reserve the outer glass bottle for the recyclable inner vial to twist into. Be sure to keep your glass bottle for your next refill.

Can I use Total RF Serum by itself?

Yes, we have clinical support to show the anti-aging benefits of using Total RF Serum alone.

How does this differ from the AMP MD System with the derma-roller?

AMP MD System amplifies and accelerates results with a patented ergonomic roller to address the following skin concerns: firmness, tone, lines, deep wrinkles, skin texture. Total RF Serum gently but effectively targets total anti-aging concerns including: elasticity, firmness, plumpness, fine lines, skin texture, even skin tone, radiance, softer more supple skin, reduced pores, revitalized skin.

Common questions about the Rodan + Fields

Total RF Serum

What is a serum?

A serum is applied to your skin after cleansing but before moisturizing creams with the intent of introducing powerful ingredients into the skin. Serums are particularly suited to this task because the formula’s lightweight texture blankets skin with a high concentration of key ingredients. This makes them a great tool for targeting specific skincare concerns.

Can the Total RF Serum for anti-aging be used with all regimens?

Yes, Total RF Serum can be used with Redefine, Reverse, Soothe, UNBLEMISH and RECHARGE regimens.

Redefine: use Total RF Serum after Step 2
Reverse: use Total RF Serum after Step 2
Soothe: use Total RF Serum after Step 2
UNBLEMISH: use Total RF Serum after Step 3
RECHARGE: use Total RF Serum after Step 1

As with any new product, we recommend users with sensitive skin to patch test the Total RF Serum before applying it to their face.

Although Total RF Serum was formulated to enhance any R+F Regimen, it does not need to be used with a R+F Regimen to address anti-aging skin concerns. The serum does not need to be used with the R+F Regimen to get results, but you’ll get better results with a Regimen.

Can I layer face serums, and in what order?

While you could choose to only use one serum based on your primary targeted need, you can layer two serums or more and still benefit from their targeted results. If layering with other Serums, the application order is Active Hydration Serum, Intensive Renewing Serum and then Total RF Serum.

Can I use the refill without the full-size Total RF Serum?

You need to reserve the outer glass bottle for the recyclable inner vial to twist into. Be sure to keep your glass bottle for your next refill.

Can I use Total RF Serum by itself?

Yes, we have clinical support to show the anti-aging benefits of using Total RF Serum alone.

How does this differ from the AMP MD System with the derma-roller?

AMP MD System amplifies and accelerates results with a patented ergonomic roller to address the following skin concerns: firmness, tone, lines, deep wrinkles, skin texture. Total RF Serum gently but effectively targets total anti-aging concerns including: elasticity, firmness, plumpness, fine lines, skin texture, even skin tone, radiance, softer more supple skin, reduced pores, revitalized skin.

What is the best R+F serum for my skin?

Choose the appropriate serum based on the following skin concerns.

Total RF Serum: Elasticity, Firmness, Plumpness, Fine Lines, Skin Texture, Even Skin Tone, Radiance, Softer More Supple Skin, Reduced Pores, Revitalized Skin

Intensive Renewing Serum: Firmness, Tone, Lines, Deep Wrinkles : Firmness, Tone, Lines, Deep Wrinkles

Active Hydration Serum: Hydration/Dry Skin : Hydration/Dry Skin

Why are face serums important for anti-aging?

As we get older skin is compromised by the natural aging process and environmental factors, resulting in numerous signs of aging such as lack of hydration, deeper lines, wrinkles, dullness + lack of firmness. Adding at least one serum to your Regimen based on your primary targeted concern amplifies specific benefits to address key signs of skin aging.

(function() { 'use strict'; // ============================================ // CONFIGURATION - EDIT THESE VALUES // ============================================ const marketingCards = [ // ============================================ // MARKETING CARDS - EVERGREEN - "Lash Day Offer" // ============================================ { // URLS to match for immediate render urlMatches: ['beauty-enhancements','lash-serum-and-eyebrow-tint'], // PLACEMENT: Choose ONE method (comment out the others) insertAtPosition: 3, // Insert AFTER this position in the grid // insertAfterProductCode: 'HRVRGG01', // Insert AFTER this CAT ID // insertBeforeProductCode: 'HAAGR', // OR insert BEFORE this CAT ID // POSITION: 'Start' or 'End' (if not set, uses insertAtPosition. If insertAtPosition exceeds product count, defaults to 'End') // placement: 'End', // 'Start' or 'End' titleText: 'YOUR LASHES.
BUT BETTER.
', bodyText: 'Celebrate National Lash Day with a boost. Get 20% off Lash Boost + a FREE Mini Eye Cream, for a limited time.', ctaText: 'USE CODE LASHDAY', ctaHref: '/shop/r-f-lash-boost/p/ENHLSH01', cardHref: '/shop/r-f-lash-boost/p/ENHLSH01', disclaimerText: '', textShadowEnabled: false, // BACKGROUND: Image URL or null for solid color backgroundImage: 'https://www.rodanandfields.com/en-us/medias/LASH-DAY-marketing-module-horizontal-image.jpg?context=bWFzdGVyfGltYWdlc3wxMTMwOTh8aW1hZ2UvanBlZ3xhRGczTDJneFppOHlPRFExTVRReE1UY3lNakkzTUM5TVFWTklMVVJCV1MxdFlYSnJaWFJwYm1jdGJXOWtkV3hsWDJodmNtbDZiMjUwWVd4ZmFXMWhaMlV1YW5CbnxhNTZkMTEyODgxNzdhM2NkNGQxODNkYmRjNWRkNGUyZDVjYjNmYjRlYWQxZjc0NjRhMGJjMjZjZjI5N2Y2YTI0', backgroundColor: '#FFFFFF', // Used only if backgroundImage is null copyBackgroundColor: '#FFFFFF', splitImageHalf: true, // LAYOUT copyAlign: 'left' }, // ============================================ // MARKETING CARDS - EVERGREEN - "Pure C Promo MC" // ============================================ { // URLS to match for immediate render urlMatches: ['best-sellers','redefine','skin-care-regimens'], // PLACEMENT: Choose ONE method (comment out the others) insertAtPosition: 3, // Insert AFTER this position in the grid // insertAfterProductCode: 'HRVRGG01', // Insert AFTER this CAT ID // insertBeforeProductCode: 'HAAGR', // OR insert BEFORE this CAT ID // POSITION: 'Start' or 'End' (if not set, uses insertAtPosition. If insertAtPosition exceeds product count, defaults to 'End') // placement: 'End', // 'Start' or 'End' titleText: 'LIMITED-TIME: PURE C EXCLUSIVE OFFERS', bodyText: 'Pair with Active Hydration Serum and save $45 or buy Pure C, get a complimentary Hydra Mask ($54 Value)', ctaText: 'Shop Now', ctaHref: '/category/face-serums', cardHref: '/category/face-serums', disclaimerText: 'Valid thru 2/28/26. See Terms & Conditions', textShadowEnabled: false, // BACKGROUND: Image URL or null for solid color backgroundImage: 'https://www.rodanandfields.com/en-us/medias/Pure-C-Promo-Marketing-Module.jpg?context=bWFzdGVyfGltYWdlc3w2NTk0MHxpbWFnZS9qcGVnfGFESXdMMmhoWmk4eU9ETTVOems1TnpjeE9UVTRNaTlRZFhKbExVTXRVSEp2Ylc4dFRXRnlhMlYwYVc1bkxVMXZaSFZzWlM1cWNHY3xhNmFmZWY2YjU3MzM5ZWY2NWNlN2Q5Njk1MWFjYTY1MzE0MWI4NzQ3OWY1YWUyNTM0NDY4YzUwMzcyYzcwY2Mz', backgroundColor: '#FFFFFF', // Used only if backgroundImage is null copyBackgroundColor: '#FFFFFF', splitImageHalf: true, // LAYOUT copyAlign: 'left' }, // ============================================ // MARKETING CARDS - EVERGREEN - "Pure C Evergreen MC" // ============================================ { // URLS to match for immediate render urlMatches: ['face-serums','anti-aging-skin-care'], // PLACEMENT: Choose ONE method (comment out the others) insertAtPosition: 3, // Insert AFTER this position in the grid // insertAfterProductCode: 'HRVRGG01', // Insert AFTER this CAT ID // insertBeforeProductCode: 'HAAGR', // OR insert BEFORE this CAT ID // POSITION: 'Start' or 'End' (if not set, uses insertAtPosition. If insertAtPosition exceeds product count, defaults to 'End') // placement: 'End', // 'Start' or 'End' titleText: 'NEW PURE C SERUM', bodyText: 'Activate your skin’s longevity for firmer, smoother, brighter skin...now and for years to come', ctaText: 'Learn More', ctaHref: '/discover/purec', cardHref: '/discover/purec', disclaimerText: '', textShadowEnabled: false, // BACKGROUND: Image URL or null for solid color backgroundImage: 'https://www.rodanandfields.com/en-us/medias/Pure-C-Evergreen-Marketing-Module.jpg?context=bWFzdGVyfGltYWdlc3w5MjQxOXxpbWFnZS9qcGVnfGFEVXhMMmhoTlM4eU9ETTVOems1TnpRMU56UXpPQzlRZFhKbExVTXRSWFpsY21keVpXVnVMVTFoY210bGRHbHVaeTFOYjJSMWJHVXVhbkJufDNkZTgzNTUzYTFjY2QwMjY2OWVlZjljODYwZmNjYWY5YzRmNGFjNWE2Y2I3YjM4YjczNTdjODhmOTQzZDcwMDY', backgroundColor: '#FFFFFF', // Used only if backgroundImage is null copyBackgroundColor: '#FFFFFF', splitImageHalf: true, // LAYOUT copyAlign: 'left' }, // ============================================ // MARKETING CARDS - EVERGREEN - "Money Back Guarantee" // ============================================ { // URLS to match for immediate render urlMatches: ['exfoliants','eye-creams-and-treatments','neck-and-decollete','reverse','soothe','unblemish'], // PLACEMENT: Choose ONE method (comment out the others) insertAtPosition: 3, // Insert AFTER this position in the grid // insertAfterProductCode: 'HRVRGG01', // Insert AFTER this CAT ID // insertBeforeProductCode: 'HAAGR', // OR insert BEFORE this CAT ID // POSITION: 'Start' or 'End' (if not set, uses insertAtPosition. If insertAtPosition exceeds product count, defaults to 'End') // placement: 'End', // 'Start' or 'End' titleText: 'Love it or get your money back.', bodyText: 'We stand behind our science, formulas + results with a 60-Day Money Back Guarantee.', ctaText: 'Learn More', ctaHref: '/satisfaction-guarantee', cardHref: '/satisfaction-guarantee', disclaimerText: '', textShadowEnabled: false, // BACKGROUND: Image URL or null for solid color backgroundImage: 'https://www.rodanandfields.com/en-us/medias/60-day-Guarantee.jpg?context=bWFzdGVyfGltYWdlc3wyNDc0OTd8aW1hZ2UvanBlZ3xhREppTDJnek1TOHlPRE01TnprNU5qRTBOamN4T0M4Mk1DMWtZWGt0UjNWaGNtRnVkR1ZsTG1wd1p3fDM1ZDU3NGEwZDllNWMxZDUwYzk1NDJhZjMwNGZkM2Y5NGEwMmM3NTQ2MzhjYTI0ZDk2NWQ4ZjJlOTY2NTJmYWE', backgroundColor: '#F5F4F2', // Used only if backgroundImage is null copyBackgroundColor: '#F5F4F2', splitImageHalf: true, // LAYOUT copyAlign: 'left' }, // ============================================ // MARKETING CARDS - EVERGREEN - "#1 Female Dermatologist Founded Skincare Brand" // ============================================= { // URLS to match for immediate render urlMatches: ['acne-pores-blackheads-skin-care','dry-skin-care','skin-care-essentials','face-moisturizers','lip-care-and-color','sensitive-skin-care','sun-protection','toners','uneven-skin-tone-and-dark-marks-skin-care'], // PLACEMENT: Choose ONE method (comment out the others) insertAtPosition: 3, // Insert AFTER this position in the grid // insertAfterProductCode: 'HRVRGG01', // Insert AFTER this CAT ID // insertBeforeProductCode: 'HAAGR', // OR insert BEFORE this CAT ID // POSITION: 'Start' or 'End' (if not set, uses insertAtPosition. If insertAtPosition exceeds product count, defaults to 'End') // placement: 'End', // 'Start' or 'End' titleText: '#1 Female Dermatologist Founded Skincare Brand in the U.S.*', bodyText: '', ctaText: 'Learn More', ctaHref: '/nx/our-story', cardHref: '/nx/our-story', disclaimerText: '*Source Euromonitor Int’l Ltd. 2024; See rodanandfields.com for details.', textShadowEnabled: false, // BACKGROUND: Image URL or null for solid color backgroundImage: 'https://www.rodanandfields.com/en-us/medias/Female-Derm.jpg?context=bWFzdGVyfGltYWdlc3wyNDQ2MTR8aW1hZ2UvanBlZ3xhR1k1TDJnellTOHlPRE01TnprNU5qUXdPRGcyTWk5R1pXMWhiR1V0UkdWeWJTNXFjR2N8NDc0NTdhYzliNzNhMTA3ZGJkYzc5NzVmNjMzNzcyMGUwYzE5OGQzMDk3MDE3ZWRhNTk2NTM3ZjZlZGZhNjdjMQ', backgroundColor: '#F5F4F2', // Used only if backgroundImage is null copyBackgroundColor: '#F5F4F2', splitImageHalf: true, // LAYOUT copyAlign: 'left' }, // ============================================ // MARKETING CARDS - EVERGREEN - "Rodan + Fields is the #1 Premium Lash Serum" // ============================================= { // URLS to match for immediate render urlMatches: [], // PLACEMENT: Choose ONE method (comment out the others) insertAtPosition: 3, // Insert AFTER this position in the grid // insertAfterProductCode: 'HRVRGG01', // Insert AFTER this CAT ID // insertBeforeProductCode: 'HAAGR', // OR insert BEFORE this CAT ID // POSITION: 'Start' or 'End' (if not set, uses insertAtPosition. If insertAtPosition exceeds product count, defaults to 'End') // placement: 'End', // 'Start' or 'End' titleText: 'Rodan + Fields is the #1 Premium Lash Serum Brand in the US in 2024*', bodyText: '', ctaText: '', ctaHref: '', cardHref: '', disclaimerText: '*Source Euromonitor International Limited; Custom research conducted June-Aug 2025, retail value RSP terms; all channels; Lash Serum including Lash Serum products sold as part of Sets and Kits', textShadowEnabled: false, // BACKGROUND: Image URL or null for solid color backgroundImage: 'https://www.rodanandfields.com/en-us/medias/Lash-Boost-MC-Image.jpg?context=bWFzdGVyfGltYWdlc3wyMDE1Mjd8aW1hZ2UvanBlZ3xhRFJsTDJneU1DOHlPRE01TnprNU5UZzRORFUzTkM5TVlYTm9MVUp2YjNOMExVMURMVWx0WVdkbExtcHdad3w2MTVjMTdmN2Q2MDJlYmIzMzhmOWQ2OTg0MmRlNTFiODg5N2Q5OTBhNDFlODQwMmNjODliMzM3Yjk3NGJiNjIz', backgroundColor: '#F5F4F2', // Used only if backgroundImage is null copyBackgroundColor: '#F5F4F2', splitImageHalf: true, // LAYOUT copyAlign: 'left' }, // ============================================ // MARKETING CARDS - EVERGREEN - "Klarna" // ============================================= { // URLS to match for immediate render urlMatches: ['regimen-sets','rf-paired-multi-action-regimens','skin-care-tools-and-accessories'], // PLACEMENT: Choose ONE method (comment out the others) insertAtPosition: 3, // Insert AFTER this position in the grid // insertAfterProductCode: 'HRVRGG01', // Insert AFTER this CAT ID // insertBeforeProductCode: 'HAAGR', // OR insert BEFORE this CAT ID // POSITION: 'Start' or 'End' (if not set, uses insertAtPosition. If insertAtPosition exceeds product count, defaults to 'End') // placement: 'End', // 'Start' or 'End' titleText: 'Buy now. Pay later.', bodyText: 'Select Klarna at checkout to split your purchase into 4 interest-free payments.', ctaText: '', ctaHref: '', cardHref: '', disclaimerText: '', textShadowEnabled: false, // BACKGROUND: Image URL or null for solid color backgroundImage: 'https://www.rodanandfields.com/en-us/medias/Klarna.jpg?context=bWFzdGVyfGltYWdlc3wzMTE3NnxpbWFnZS9qcGVnfGFETmlMMmc1TVM4eU9ETTVOems1T1RFMk1UTTNOQzlMYkdGeWJtRXVhbkJufDUwMzJkNzBjNzRjZmMxYzc2MjE5NWEyNjIwOTJmYzg5ZDE1NjQ1Y2U4MDQ3ZTg2OTI3ZjIxMzE1OGU3OGE2NWI', backgroundColor: '#F5F4F2', // Used only if backgroundImage is null copyBackgroundColor: '#F5F4F2', splitImageHalf: true, // LAYOUT copyAlign: 'left' } ]; // ============================================ // MODULE HTML GENERATOR // ============================================ function generateModuleHTML(cfg) { const alignMap = { left: 'flex-start', center: 'center', right: 'flex-end' }; const safeAlign = ['left','center','right'].includes(cfg.copyAlign) ? cfg.copyAlign : 'center'; const bgStyle = cfg.backgroundImage ? `background: url('${cfg.backgroundImage}') center/cover no-repeat;` : `background: ${cfg.backgroundColor}`; const shadowStyle = cfg.textShadowEnabled ? 'text-shadow: 0 1px 2px rgba(0,0,0,0.6);' : ''; // Split Image Half Layout if (cfg.splitImageHalf) { const splitImageStyle = `${cfg.backgroundImage ? `--split-image-url: url('${cfg.backgroundImage}');` : ''}`; const cardAttr = cfg.cardHref ? `data-card-href="${cfg.cardHref}"` : ''; const cardClass = cfg.cardHref ? ' rf-card-clickable' : ''; return `

${cfg.titleText.replace(/\n/g, '
')}

${cfg.bodyText ? `

${cfg.bodyText}

` : ''} ${cfg.ctaText && cfg.ctaText.trim() ? `${cfg.ctaText}` : ''} ${cfg.disclaimerText ? `
${cfg.disclaimerText}
` : ''}
`; } // Default horizontal layout const cardAttr = cfg.cardHref ? `data-card-href="${cfg.cardHref}"` : ''; const cardClass = cfg.cardHref ? ' rf-card-clickable' : ''; return `

${cfg.titleText.replace(/\n/g, '
')}

${cfg.bodyText ? `

${cfg.bodyText}

` : ''} ${cfg.ctaText && cfg.ctaText.trim() ? `${cfg.ctaText}` : ''} ${cfg.disclaimerText ? `
${cfg.disclaimerText}
` : ''}
`; } // PDP detection helper function isPDP() { try { const path = (window.location && window.location.pathname) || ''; // PDP URLs include "/p/" followed by a code return path.includes('/p/'); } catch (e) { return false; } } // Return cards whose urlMatches match a full path segment (not substring) function getActiveCards() { const href = (window.location && window.location.href || '').toLowerCase(); const path = (window.location && window.location.pathname || '').toLowerCase(); const segments = path.split('/').filter(Boolean); // path parts without empty strings const matchesSegment = (needle) => { if (!needle) return false; const n = String(needle).toLowerCase(); // exact segment match, or common category patterns return segments.includes(n) || path.endsWith('/' + n) || path.includes('/shop/' + n + '/') || href.includes('cgid=' + encodeURIComponent(n)); }; return marketingCards.filter(card => Array.isArray(card.urlMatches) && card.urlMatches.some(matchesSegment)); } // ============================================ // PRODUCT DETECTION // ============================================ let injected = false; function filterProductElements(elements) { return elements.filter(el => { const tag = el.tagName ? el.tagName.toLowerCase() : ''; if (tag === 'button' || tag === 'a') return false; const role = (el.getAttribute && el.getAttribute('role')) || ''; if (role === 'button' || role === 'link') return false; if (el.hasAttribute && el.hasAttribute('data-copilot-module')) return false; if (el.closest && el.closest('.add-to-cart, .product-cta, .product-actions, .pdp-add-to-cart, .quickbuy')) return false; return true; }); } function findProducts() { const selectors = [ '[data-product-code]', '[data-product-id]', '.product-item', '.product-card', '.product-tile', '.product', '.js-product', 'article.product', '.product-grid-item', '.product-list-item' ]; for (let selector of selectors) { const elements = document.querySelectorAll(selector); if (elements.length > 0) { console.log(`Found ${elements.length} products using: ${selector}`); return filterProductElements(Array.from(elements)); } } console.warn('No products found'); return []; } function getProductCode(el) { return el.getAttribute('data-product-code') || el.getAttribute('data-product-id') || el.getAttribute('data-sku') || el.querySelector('[data-product-code]')?.getAttribute('data-product-code') || el.querySelector('[data-product-id]')?.getAttribute('data-product-id') || el.querySelector('a[href*="/shop/"]')?.href.split('/p/')[1]?.split('?')[0] || null; } // ============================================ // INJECTION LOGIC // ============================================ function injectModule() { if (injected) return; // Guard: never inject on PDPs if (isPDP()) { console.warn('PDP detected; skipping marketing card injection.'); return; } const cards = getActiveCards(); if (!cards || cards.length === 0) { console.warn('No marketing card configured for this URL'); return; } // Only consider products inside .mdc-layout-grid__inner if present let products = []; const gridInner = document.querySelector('.mdc-layout-grid__inner'); if (gridInner) { // Find all product elements inside the grid products = filterProductElements(Array.from(gridInner.querySelectorAll('[data-product-code], [data-product-id], .product-item, .product-card, .product-tile, .product, .js-product, article.product, .product-grid-item, .product-list-item'))); } else { products = findProducts(); } if (products.length === 0) return; console.log(`${cards.length} marketing card(s) matched this URL`); // Log all found product codes and positions for debugging console.log('Product codes and positions found:'); products.forEach((p, i) => { const pos = p.getAttribute('data-position'); const code = getProductCode(p); console.log(` Index ${i + 1} | Position: ${pos} | Code: ${code || 'N/A'}`); }); // Try to inject each matching card let anyInjected = false; cards.forEach(card => { let placed = false; // Placement logic if (!placed && card.placement) { if (card.placement.toLowerCase() === 'start' && products.length > 0) { console.log('Inserting module at START (before first product)'); insertModule(products[0], 'before', card); placed = true; } else if (card.placement.toLowerCase() === 'end' && products.length > 0) { console.log('Inserting module at END (after last product)'); insertModule(products[products.length - 1], 'after', card); placed = true; } } // Fallbacks: by product code or position if (!placed) { for (let i = 0; i < products.length; i++) { const code = getProductCode(products[i]); if (card.insertAfterProductCode && code === card.insertAfterProductCode) { console.log(`Inserting module AFTER product code: ${code}`); insertModule(products[i], 'after', card); placed = true; break; } if (card.insertBeforeProductCode && code === card.insertBeforeProductCode) { console.log(`Inserting module BEFORE product code: ${code}`); insertModule(products[i], 'before', card); placed = true; break; } } } if (!placed && card.insertAtPosition) { let targetProduct = null; // Try to find by data-position attribute first targetProduct = Array.from(products).find(p => parseInt(p.getAttribute('data-position')) === card.insertAtPosition ); // If not found, fallback to Nth product in the array (1-based) if (!targetProduct && products.length >= card.insertAtPosition) { targetProduct = products[card.insertAtPosition - 1]; } // If still not found, fallback to last product in gridInner if (!targetProduct && products.length > 0) { targetProduct = products[products.length - 1]; } if (targetProduct) { console.log(`Inserting module after product (insertAtPosition=${card.insertAtPosition})`); insertModule(targetProduct, 'after', card); placed = true; } } if (!placed) { console.warn(`Target not found for card. Check insertAfterProductCode, insertBeforeProductCode, or insertAtPosition configuration.`); } else { anyInjected = true; } }); if (anyInjected) { injected = true; // Ensure any end-placed cards are positioned after the latest product set repositionEndCards(); } } function insertModule(target, position, cardConfig) { const wrapper = document.createElement('div'); wrapper.innerHTML = generateModuleHTML(cardConfig).trim(); const base = target.closest && target.closest('[data-product-code], [data-product-id], .product-item, .product-card, .product-tile, .product, .js-product, article.product, .product-grid-item, .product-list-item') || target; const baseTag = (base.tagName || '').toLowerCase(); const safeTag = (baseTag === 'button' || baseTag === 'a') ? 'div' : (baseTag || 'div'); const classList = (base.className || '') .split(/\s+/) .filter(Boolean) .filter(c => !/(^|-)btn($|-)|button|cta|add-to-cart|purchase|subscribe|link/i.test(c)) .join(' '); const container = document.createElement(safeTag); if (classList) container.className = classList; container.setAttribute('data-copilot-module', 'true'); if (cardConfig && cardConfig.placement) { container.setAttribute('data-copilot-placement', String(cardConfig.placement).toLowerCase()); } container.appendChild(wrapper.firstElementChild); if (position === 'after') { base.parentNode.insertBefore(container, base.nextSibling); } else { base.parentNode.insertBefore(container, base); } // Make entire card clickable if data-card-href is present const clickable = container.querySelector('.rf-card-clickable[data-card-href]'); if (clickable) { const href = clickable.getAttribute('data-card-href'); clickable.setAttribute('role', 'link'); clickable.setAttribute('tabindex', '0'); const navigate = () => { try { window.location.assign(href); } catch(e) { window.location.href = href; } }; clickable.addEventListener('click', (e) => { const insideAnchor = e.target.closest('a'); if (insideAnchor) return; // allow inner links like CTA/disclaimer navigate(); }); clickable.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); navigate(); } }); } console.log('Marketing module injected successfully!'); } // Reposition any cards configured with placement: 'End' after dynamic loads function repositionEndCards() { const endCards = Array.from(document.querySelectorAll('[data-copilot-module="true"][data-copilot-placement="end"]')); if (endCards.length === 0) return; // Determine current product list inside grid const gridInner = document.querySelector('.mdc-layout-grid__inner'); const productSelector = '[data-product-code], [data-product-id], .product-item, .product-card, .product-tile, .product, .js-product, article.product, .product-grid-item, .product-list-item'; let products = []; if (gridInner) { products = Array.from(gridInner.querySelectorAll(productSelector)); } else { products = Array.from(document.querySelectorAll(productSelector)); } products = products.filter(el => !el.hasAttribute('data-copilot-module')); if (products.length === 0) return; const lastProduct = products[products.length - 1]; endCards.forEach(card => { if (lastProduct.nextSibling !== card) { try { lastProduct.parentNode.insertBefore(card, lastProduct.nextSibling); } catch (e) {} } }); } function isModulePresent() { return document.querySelector('[data-copilot-module="true"]') !== null; } // ============================================ // INITIALIZATION - IMMEDIATE LOAD // ============================================ function init() { injectModule(); // Quick retries for fast page load if (!injected) { setTimeout(injectModule, 100); setTimeout(injectModule, 300); setTimeout(injectModule, 500); setTimeout(injectModule, 1000); } } // Run immediately init(); // Also run on DOMContentLoaded as backup if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } // Watch for dynamically loaded products const observer = new MutationObserver(() => { clearTimeout(window.moduleInjectionTimeout); window.moduleInjectionTimeout = setTimeout(() => { if (!isModulePresent()) { injected = false; injectModule(); } repositionEndCards(); }, 120); }); // Start observing immediately const startObserver = () => { const container = document.querySelector('.product-grid, .product-list, .products, main, body'); if (container) { observer.observe(container, { childList: true, subtree: true }); } }; startObserver(); setTimeout(startObserver, 500); })();