Customizing the Affinity customer portal theme
The Affinity customer portal theme can be customized and updated to match your brand. This guide explains how to customize your themes appearance and advanced configuration options with Affinity.
Before you start
- Stores using Hosted by Recharge and Embedded in platform storefront can add CSS customizations through your Recharge customer portal settings.
- If your color changes do not reflect when saved, ensure the theme.liquid file contains a proper open <body> and close </body> tag.
- Customizing the Affinity customer portal theme requires custom code and is not supported by Recharge as per the design and integration policy. If you require further assistance from a developer, visit the Recharge Agency Partner Directory.
Customize the theme appearance
The Affinity customer portal theme can be customized and updated to match your brand. Stores set to Embedded in platform storefront make customizations directly in the Shopify Theme Editor and can use CSS while stores using Hosted by Recharge must make customizations using CSS.
Shopify's theme editor
Transform the look and feel of your customer portal by adjusting simple settings.
Custom CSS
Most styles in Affinity are stored using CSS variables. You can easily overwrite the default values by targeting the .recharge-theme class and customizing default variables.
Customize the following variables
/* Color: Brand */ --recharge-color-brand: #467c99; --recharge-color-brand-120: #38637a; --recharge-color-brand-20: #6b96ad; --recharge-color-brand-40: #90b0c2; --recharge-color-brand-60: #bed1db; --recharge-color-brand-75: #e3ebf0; --recharge-color-brand-85: #f6f8fa; /* Color: Neutral */ --recharge-color-neutral: #0b1317; --recharge-color-neutral-80: #3c4245; --recharge-color-neutral-70: #545a5d; --recharge-color-neutral-40: #9da1a2; --recharge-color-neutral-10: #e7e7e8; /* Color: Positive */ --recharge-color-positive120: hsl(148, 100%, 27%); --recharge-color-positive: hsl(148, 100%, 33%); --recharge-color-positive80: hsl(148, 57%, 46%); --recharge-color-positive60: hsl(148, 49%, 60%); --recharge-color-positive40: hsl(148, 49%, 73%); --recharge-color-positive20: hsl(148, 50%, 87%); --recharge-color-positive10: hsl(148, 49%, 93%); /* Color: Caution */ --recharge-color-caution120: hsl(43, 100%, 40%); --recharge-color-caution: hsl(43, 100%, 50%); --recharge-color-caution80: hsl(43, 100%, 60%); --recharge-color-caution60: hsl(43, 100%, 70%); --recharge-color-caution40: hsl(43, 100%, 80%); --recharge-color-caution20: hsl(43, 100%, 90%); --recharge-color-caution10: hsl(43, 100%, 95%); /* Color: Critical */ --recharge-color-critical120: hsl(12, 87%, 40%); --recharge-color-critical: hsl(12, 87%, 50%); --recharge-color-critical80: hsl(12, 86%, 70%); --recharge-color-critical60: hsl(12, 85%, 80%); --recharge-color-critical40: hsl(12, 85%, 80%); --recharge-color-critical20: hsl(12, 85%, 90%); --recharge-color-critical10: hsl(12, 85%, 95%); /* App */ --recharge-app-background: transparent; --recharge-app-container: 1144px; --recharge-app-vertical-padding: 0px; --recharge-app-zIndex: 9999999; --recharge-views-background: #FFFFFF; --recharge-view-container: 752px; /* Images */ --recharge-images-ratio: 1; /* Corners */ --recharge-corners-radius: 8px; /* Cards */ --recharge-cards-background: #FFFFFF; --recharge-cards-border-color: var(--recharge-cards-background); /* Typography */ --recharge-typography-light: #FFFFFF; --recharge-typography-primary: var(--recharge-color-neutral); --recharge-typography-secondary: var(--recharge-color-neutral-70); --recharge-typography-scale: 16px; --recharge-typography-size-1: calc(3 * var(--recharge-typography-scale)); --recharge-typography-size-2: calc(2.25 * var(--recharge-typography-scale)); --recharge-typography-size-3: calc(1.625 * var(--recharge-typography-scale)); --recharge-typography-size-4: calc(1.25 * var(--recharge-typography-scale)); --recharge-typography-size-5: calc(1 * var(--recharge-typography-scale)); --recharge-typography-size-6: calc(0.875 * var(--recharge-typography-scale)); --recharge-typography-size-7: calc(0.75 * var(--recharge-typography-scale)); /* Buttons */ --recharge-button-brand: var(--recharge-color-brand); --recharge-button-color: #FFFFFF; --recharge-button-border-radius: calc(var(--recharge-corners-radius) / 2); --recharge-button-font-family: inherit;
Target specific Recharge CSS classes to customize the look and feel of the following components
Do not target other classes in the Affinity customer portal theme other than the classes provided. Recharge provides no guarantee that these selectors will work in the future and is subject to change.
Text
recharge-text
recharge-text-p1
recharge-text-p2
recharge-text-p3
recharge-text-p3-compact
recharge-text-p4
recharge-text-p5
Heading
recharge-heading
recharge-heading-h1
recharge-heading-h2
recharge-heading-h3
recharge-heading-h4
Button
recharge-button
recharge-button-primary
recharge-button-secondary
recharge-button-tertiary
Other elements
recharge-action-link
recharge-alert
recharge-badge
recharge-card
recharge-container
rechrge-icon
recharge-image
recharge-pull
recharge-textarea
recharge-textfield
Example code for updating heading
.recharge-heading {
font-family: sans-serif;
letter-spacing: 1px;
}
Sections
Changes made will apply only on the specific section updated.
.recharge-section-next-order-actions
.recharge-section-next-order-list
.recharge-section-product-carousel
You can target specific components in a section. For example, .recharge-section-next-order-actions .recharge-button
will select all buttons in the next-order-actions section.
Theme
Customize the following variable targeting the .recharge-theme
class. .recharge-theme
should only contain CSS variables. Do not add additional styles such as margin or paddings.
/* Color: Brand */
--recharge-color-brand: #467c99;
--recharge-color-brand-120: #38637a;
--recharge-color-brand-20: #6b96ad;
--recharge-color-brand-40: #90b0c2;
--recharge-color-brand-60: #bed1db;
--recharge-color-brand-75: #e3ebf0;
--recharge-color-brand-85: #f6f8fa;
/* Color: Neutral */
--recharge-color-neutral: #0b1317;
--recharge-color-neutral-80: #3c4245;
--recharge-color-neutral-70: #545a5d;
--recharge-color-neutral-40: #9da1a2;
--recharge-color-neutral-10: #e7e7e8;
/* Color: Positive */
--recharge-color-positive120: hsl(148, 100%, 27%);
--recharge-color-positive: hsl(148, 100%, 33%);
--recharge-color-positive80: hsl(148, 57%, 46%);
--recharge-color-positive60: hsl(148, 49%, 60%);
--recharge-color-positive40: hsl(148, 49%, 73%);
--recharge-color-positive20: hsl(148, 50%, 87%);
--recharge-color-positive10: hsl(148, 49%, 93%);
/* Color: Caution */
--recharge-color-caution120: hsl(43, 100%, 40%);
--recharge-color-caution: hsl(43, 100%, 50%);
--recharge-color-caution80: hsl(43, 100%, 60%);
--recharge-color-caution60: hsl(43, 100%, 70%);
--recharge-color-caution40: hsl(43, 100%, 80%);
--recharge-color-caution20: hsl(43, 100%, 90%);
--recharge-color-caution10: hsl(43, 100%, 95%);
/* Color: Critical */
--recharge-color-critical120: hsl(12, 87%, 40%);
--recharge-color-critical: hsl(12, 87%, 50%);
--recharge-color-critical80: hsl(12, 86%, 70%);
--recharge-color-critical60: hsl(12, 85%, 80%);
--recharge-color-critical40: hsl(12, 85%, 80%);
--recharge-color-critical20: hsl(12, 85%, 90%);
--recharge-color-critical10: hsl(12, 85%, 95%);
/* App */
--recharge-app-background: transparent;
--recharge-app-container: 1144px;
--recharge-app-vertical-padding: 0px;
--recharge-app-zIndex: 9999999;
--recharge-views-background: #FFFFFF;
--recharge-view-container: 752px;
/* Images */
--recharge-images-ratio: 1;
/* Corners */
--recharge-corners-radius: 8px;
/* Cards */
--recharge-cards-background: #FFFFFF;
--recharge-cards-border-color: var(--recharge-cards-background);
/* Typography */
--recharge-typography-heading-font-family: inherit;
--recharge-typography-heading-font-weight: 600;
--recharge-typography-body-font-family: inherit;
--recharge-typography-body-font-weight: 400;
--recharge-typography-light: #FFFFFF;
--recharge-typography-primary: var(--recharge-color-neutral);
--recharge-typography-secondary: var(--recharge-color-neutral-70);
--recharge-typography-scale: 16px;
--recharge-typography-size-1: calc(3 * var(--recharge-typography-scale));
--recharge-typography-size-2: calc(2.25 * var(--recharge-typography-scale));
--recharge-typography-size-3: calc(1.625 * var(--recharge-typography-scale));
--recharge-typography-size-4: calc(1.25 * var(--recharge-typography-scale));
--recharge-typography-size-5: calc(1 * var(--recharge-typography-scale));
--recharge-typography-size-6: calc(0.875 * var(--recharge-typography-scale));
--recharge-typography-size-7: calc(0.75 * var(--recharge-typography-scale));
/* Buttons */
--recharge-button-brand: var(--recharge-color-brand);
--recharge-button-color: #FFFFFF;
--recharge-button-border-radius: calc(var(--recharge-corners-radius) / 2);
--recharge-button-font-family: inherit;
/* Carousel */
--recharge-carousel-thumbnail-size: 124px
Product upsell carousel
The product carousel can be added by enabling Add products to subscription in your customer portal settings under Customer portal controls. When enabling your carousel, the products displayed will be based on the settings you choose under products available for purchase.
You can display a different set of products if the options of All products, Recharge products, or Recharge collections are limited for your store's needs.
Advanced configuration options
In addition to the default customer portal settings, Affinity provides extra configurations that help you to personalize your portal. Optimize your upsells and improve retention when adding these customizations.
Customize the product upsell carousel
Add a script to customize your product carousel:
- Click Storefront in your merchant portal and select Customer Portal.
- Add this script to the Footer HTML/CSS/JS section under Customize styles.
-
<script>
window.RechargeExtensions = {
product_carousel_collection_ids: ["6915"],
};
</script> - Be sure to replace '6915' with your product collection IDs. Recharge collection IDs can be found by visiting the desired collection page and copying the last digits in the URL.
-
- Scroll to the bottom and click Save.
Subscription swap options
Product swaps can be added by enabling Swap product in your customer portal settings under Customer portal controls. When enabling product swaps, the products displayed will be based on the settings you choose for products available for purchase. Customize the products that display on your swap list by product or variant.
To configure a custom product swap:
- Click Storefront in your merchant portal and select Customer Portal.
- Add one of the following scripts to the Footer HTML/CSS/JS section under Customize styles depending on by product or variant.
-
<script>
window.RechargeExtensions = {
swaps: {
// Use for product swap by product
// 6734589067319 -> Your shopify product id
// 6915 -> Your recharge collection id
6734589067319: ["6915"],
// Use for product swap by variant
// 40023201316919 -> Your shopify variant id
// 7351 -> Your recharge collection id
40023201316919: ["7351"],
},
};
</script>
-
- Scroll to the bottom and click Save.
Reschedule options
The ability to update the next order date for a product or group of products can be added by enabling Edit upcoming date in your customer portal settings under Customer portal controls. Once enabled, your customers will have the flexibility to reschedule their orders with ease, using the quick delay frequency options and calendar presented to them.
To customize the quick delay frequency options and available dates in the calendar:
- Click Storefront in your merchant portal and select Customer Portal.
-
Add this script to the Footer HTML/CSS/JS section under Customize styles.
-
<script> window.RechargeExtensions = { reschedule: { disableQuickOptions: false, disableCalendar: false, quickOptions: [ { frequency: 2, unit: 'week', }, { frequency: 4, unit: 'week', }, ], calendar: { enableDaysOfWeek: ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'], enableDaysOfMonth: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], enableMonthsOfTheYear: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] } } } </script>
-
- Scroll to the bottom and click Save.
Frequency options
Restrict the frequency options available to customers, providing them flexibility while also maintaining business viability. For example, only allow customers to select frequencies within a 15 to 45-day range.
To customize the frequency options to a specific range:
- Click Storefront in your merchant portal and select Customer Portal.
- Confirm that your customer portal settings have the option customer can choose any frequency enabled.
- Customize the following script to your needs and add it to the Footer HTML/CSS/JS section under Customize styles.
<script> window.RechargeExtensions = { subscription: { frequencyUnitsRanges: { day: { min: 1, max: 90 }, week: { min: 1, max: 52 }, month: { min: 3, max: 9 } } } } </script>
Contextual feature control
You can configure the options for ordering now, skipping, or rescheduling using the store settings. However, you may need to override these settings for specific contexts, such as the next order view or for certain products. Contextual feature control enables you to limit or modify features in these specific contexts, ensuring that your customers have the best possible experience.
To configure contextual feature control:
- Click Storefront in your merchant portal and select Customer Portal.
-
Add a customized version of this script to the Footer HTML/CSS/JS section under Customize styles.
-
<script> window.RechargeExtensions = { orderNow: { disabledForNextOrder: false, }, reschedule: { disabledForNextOrder: false, disabledForProductIds: [6734589067319], }, skip: { disabledForNextOrder: false, disabledForProductIds: [6734589067319], }, }; </script>
-
- Scroll to the bottom and click Save.
Dates format
Customize how your dates are displayed with a long or short style format.
Long style
Use a long date format in areas where full context is needed such as a customers next order date. This format includes weekday, month, day, and year.
Short style
Use a short date format to display minimal information about the date. This format includes month and day.
Default configuration
You can extend each individual style and customize how dates are displayed, the configuration follows DateTimeFormat format:
window.RechargeExtensions = {
dates: {
short: {
day: "numeric",
month: "long",
},
long: {
weekday: "short",
day: "numeric",
month: "long",
year: "numeric",
},
},
};
Options
Possible values to customize how dates are displayed:
window.RechargeExtensions = {
dates: {
short: {
weekday: "long | narrow",
day: "numeric | 2-digit",
month: "short | numeric | narrow | long | 2-digit",
year: "numeric | 2-digit",
},
},
};
Examples
// Example 01 - Include a `year` in `short` format
window.RechargeExtensions = {
dates: {
short: {
year: "numeric",
},
},
};
// Example 02 - Removing the `weekday` in `long` format:
window.RechargeExtensions = {
dates: {
long: {
weekday: undefined,
},
},
};
// Example 03 - Display `long` as `1/1/2023` style:
window.RechargeExtensions = {
dates: {
long: {
weekday: undefined,
day: "numeric",
month: "numeric",
year: "numeric",
},
},
};
Extend the portal with custom content and functionality using slots
Slots allow you to personalize the Affinity customer portal theme with custom content. Promote featured products or collections, add third-party widgets, display a banner ad, or add custom components using slots. Created with a script tag that holds your custom code contents, Affinity will automatically detect and inject the content into the requested location.
This example adds the contents of <p>hello world</p> into the header:
<script type="text/html" data-recharge-slot="header">
<p>hello world</p>
</script>
Slots can be configured in the following locations:
- header: beginning of every page
- footer: end of every page
- sidebar: sidebar before logout
- homepage-header: beginning of the homepage
- homepage-footer: end of the homepage
- homepage-sidebar: sidebar before logout, only in the homepage
Establish two-way communication between custom content and Affinity
Communicate with Affinity
Content within slots communicates with Affinity by emitting events. Events trigger designated actions. For example, you could use the following script to emit a refresh event to trigger a page refresh, ensuring up-to-date data is displayed if a customer adds a product to their next order from within a slot:
<script>
refreshCustomerPortalState = new CustomEvent("Affinity:refresh");
document.dispatchEvent(refreshCustomerPortalState)
</script>
Refer to the following chart for a list of supported events and their associated actions:
Event |
Action |
Affinity:refresh |
Trigger a soft refresh of the page. |
Recharge::order::openOrderNowModal |
Open the order now modal for the next scheduled order in the /overview page. |
Recharge::order::openRescheduleModal |
Open the reschedule modal for the next scheduled order in the /overview page. |
Recharge::order::openSkipModal |
Open the skip modal for the next scheduled order in the /overview page |
Recharge::order::unskip |
Call unskip function within in the /overview page to unskip the next scheduled order. |
Recharge::order::openDiscountModal |
Open the discount modal from the order summary in the /overview page. |
Listen to Affinity
You can listen for specific events to respond to changes occurring in Affinity. For example, you could use the following script to listen to the reschedule
event to update a custom slot that displays the customer's next order date:
document.addEventListener( "Recharge::action::reschedule", (event) = { //Refresh your slot custom content } );
</script>
You can also leverage these specific events to monitor customer actions. Use the events listed below with the available click events to transmit pertinent data to your preferred analytics tools:
Action |
Event |
Payload |
Skip |
Recharge::action::skip |
|
Unskip |
Recharge::action::unskip |
|
Order Now |
Recharge::action::orderNow |
|
Reschedule |
Recharge::action::reschedule |
|
Create personalized flows using events
Affinity provides the means to craft user experiences designed to meet your unique business needs. When a customer initiates an action, you gain the capacity to intercept the default behavior and initiate your custom flow for actions like skipping, rescheduling, or canceling.
Available events
These events are triggered when a user clicks a button or link to initiate an action:
- Skip:
'Recharge::click::skip'
- Unskip:
'Recharge::click::unskip'
- Order now:
'Recharge::click::orderNow'
- Reschedule:
'Recharge::click::reschedule'
- Cancel:
'Recharge::extension::cancellation_flow'
Example: Prevent cancellation for specific products
As a merchant, I want to stop customers from canceling certain products (ID: "8042064838908") on my store. Instead, I want to guide them to contact me for assistance.
To achieve this, when a cancellation is attempted, the script will listen for the cancellation event. Then, it checks if the product being canceled matches the restricted IDs. If it does, it interrupts the cancellation process and displays a message urging customers to reach out to support. For all other products, the regular cancellation process will proceed without any interruptions.
<script> // Define the list of product IDs that are not eligible for direct cancellation const uncancellableProductIds = [8042064838908]; // Customize the message to guide customers to contact you const alertMessage = "To cancel this product, please reach out to us at contact@gmail.com"; // Listen for the cancellation flow event document.addEventListener( "Recharge::extension::cancellation_flow", (event) => { const { subscription } = event.detail; const subscriptionProductId = subscription.shopify_product_id; // Check if the product is in the list of uncancellable products if (uncancellableProductIds.includes(subscriptionProductId)) { // Prevent the default cancellation flow event.preventDefault(); // Display an alert to guide customers window.alert(alertMessage); } } ); </script>
The following image is an example of how the storefront will look with the script implemented.