Skip to main content

spektrix-memberships

Overview

The spektrix-memberships web component is used to offer your clients customers dynamic ways to purchase memberships online. This document is intended to give you an in-depth view of the functionality and configuration of the spektrix-memberships element.

Embedding the component

The below is a basic example of an HTML webpage that will display the component. For a full step-by-step guide to implmentation Spektrix Web Components, see here.

Loading code

Between the <head> tags of your page, ensure you have the following script which defines the custom element:

<script src="https://webcomponents.spektrix.com/stable/spektrix-component-loader.js" async></script>

Basic example

The below illustrates a basic example of how you could use the element on your page. You will need to change the client-name, custom-domain, and membership-id to match those of your client's.

More examples can be found in the code samples page

<spektrix-memberships client-name="thetheatre" custom-domain="tickets.thetheatre.org" membership-id="1213ANPPNPTJDSBPNJDDPKRNVDCBQQRDC">
<h2>Premium Membership</h2>
<button data-submit-membership>Buy membership</button>
<label for="autorenew">
<input type="checkbox" name="autorenew" data-set-autorenew>Autorenew?
</label>
<div data-success-container style="display: none;">Successfully added to basket!</div>
<div data-fail-container style="display: none;">Failed to add to basket</div>
</spektrix-memberships>

Example with membership data display

This example shows how to use the component to automatically fetch and display membership details from the API:

<spektrix-memberships client-name="thetheatre" custom-domain="tickets.thetheatre.org" membership-id="1213ANPPNPTJDSBPNJDDPKRNVDCBQQRDC">
<h2 data-name>Loading...</h2>
<p data-description>Loading description...</p>
<div data-html-description>Loading HTML description...</div>
<img data-image-url style="max-width: 300px;" />
<div>
<strong>Price:</strong> $<span data-price>0</span>
</div>
<div>
<strong>Renewal Price:</strong> $<span data-renewal-price>0</span>
</div>
<button data-submit-membership>Buy membership</button>
<div data-success-container style="display: none;">Successfully added to basket!</div>
<div data-fail-container style="display: none;">Failed to add to basket</div>
</spektrix-memberships>

Example with customer ownership check

This example shows different content based on whether the customer already holds the membership:

<spektrix-memberships client-name="thetheatre" custom-domain="tickets.thetheatre.org" membership-id="1213ANPPNPTJDSBPNJDDPKRNVDCBQQRDC">
<h2>Premium Membership</h2>

<!-- Shown when customer already owns this membership -->
<div data-customer-holds-membership style="display: none;">
<h3>You're a Member!</h3>
<p>You already have this membership. Thank you for your support!</p>
</div>

<!-- Shown when customer does NOT own this membership -->
<div data-customer-does-not-hold-membership style="display: none;">
<h3 data-name>Membership Details</h3>
<p data-description>Membership description will appear here</p>
<div>
<strong>Price:</strong> $<span data-price>0</span>
</div>
<button data-submit-membership>Add to Basket</button>
<label>
<input type="checkbox" data-set-autorenew> Auto-renew membership
</label>
</div>

<div data-success-container style="display: none;">Successfully added to basket!</div>
<div data-fail-container style="display: none;">Failed to add to basket</div>
</spektrix-memberships>

Example with variable price membership

This example shows how to handle variable value memberships where customers can choose their own price:

<spektrix-memberships client-name="thetheatre" custom-domain="tickets.thetheatre.org" membership-id="1213ANPPNPTJDSBPNJDDPKRNVDCBQQRDC">
<h2 data-name>Membership Name</h2>

<!-- Shown only for fixed-price memberships -->
<div data-is-not-variable-membership style="display: none;">
<h4>Fixed Price Membership</h4>
<div>$<span data-price>0</span></div>
<button data-submit-membership>Add to Basket</button>
</div>

<!-- Shown only for variable-price memberships -->
<div data-is-variable-membership style="display: none;">
<h4>Choose Your Price</h4>
<p>Select an amount between $<span data-price>0</span> and $<span data-max-price>0</span></p>
<input
type="number"
data-variable-price-input
placeholder="Enter amount"
/>
<button data-submit-membership>Add to Basket</button>
</div>

<div data-success-container style="display: none;">Successfully added to basket!</div>
<div data-fail-container style="display: none;">Failed to add to basket</div>
</spektrix-memberships>

Example with loading states

This example shows how to provide visual feedback while data is being loaded:

<spektrix-memberships client-name="thetheatre" custom-domain="tickets.thetheatre.org" membership-id="1213ANPPNPTJDSBPNJDDPKRNVDCBQQRDC">
<!-- Loading container shown by default while fetching data -->
<div data-loading-container style="display: block;">
<p>Loading membership details...</p>
</div>

<!-- Loaded container hidden by default, shown after data is loaded -->
<div data-loaded-container style="display: none;">
<h2 data-name>Membership Name</h2>
<p data-description>Description</p>
<div>Price: $<span data-price>0</span></div>
<button data-submit-membership>Add to Basket</button>
</div>

<div data-success-container style="display: none;">Successfully added to basket!</div>
<div data-fail-container style="display: none;">Failed to add to basket</div>
</spektrix-memberships>

Example with membership period

This example shows how to display and format membership period information with multi-language support:

<spektrix-memberships client-name="thetheatre" membership-id="1213ANPPNPTJDSBPNJDDPKRNVDCBQQRDC" culture="en">
<h2 data-name>Membership Name</h2>

<div>
<strong>Membership Period:</strong>
<span data-membership-period
data-period-format-yearsmonthsdays="{years} year(s), {months} month(s), and {days} day(s)"
data-period-format-weeksdays="{weeks} week(s) and {days} day(s)"
data-period-format-fixed="Valid until a fixed date"
data-period-format-openended="Lifetime membership - never expires"
data-period-format-yearsmonthsdays-fr="{years} an(s), {months} mois, et {days} jour(s)"
data-period-format-weeksdays-fr="{weeks} semaine(s) et {days} jour(s)"
data-period-format-fixed-fr="Valide jusqu'à une date fixe"
data-period-format-openended-fr="Adhésion à vie - n'expire jamais">
</span>
</div>

<button data-submit-membership>Purchase Membership</button>
</spektrix-memberships>

Handling feedback from the component

When memberships are added to the basket through this component, you will need to provide feedback to your users or perform other actions based on whether this happened successfully or there was an issue. The following built in functionality is provided to assist you with this.

At this point, it is worth noting that this component does not come with any client side validation but should work well with existing libraries should you wish to use them.

Success/fail containers

If you place an element in the component that has the attribute data-success-container and one with the data-fail-container and set display: none inline on these elements, the component will display or hide these containers based on whether the membership was successfully added to the basket.

If the membership was successfully added to the basket, it will show the element containing the data-success-container attribute.

If the membership was not successfully added to the basket due to an invalid value being sent (eg - an incorrect membership ID) or there was another issue with the request (eg - membership is no longer available), it will show the element containing data-fail-container and replace it's contents with the error that came back from the server.

If the membership was not successfully added to the basket because the user is offline or something went wrong handling the request, the element containing data-fail-container is shown with the content that is stored within it.

<div data-success-container style="display: none;">Insert success content/markup here</div>
<div data-fail-container style="display: none;">Insert failure content/markup here</div>

These elements are not required for the component to function and their omission does not cause any issues. You could instead build out your own feedback using the success/fail events.

Success/fail events

As well as success/fail containers, the component itself will emit a custom event of either "success" or "fail" which you can use to provide your own custom feedback to your users. The events also contain the object that is returned from the server which in the case of "success" will describe the users current basket and or, in the case of "fail", it will return the error object provided by the server.

To see this in action, add the below to your page to see the response in your console:

var component = document.querySelector('spektrix-memberships');
component.addEventListener('success', function (e) {
console.log('event', e)
})

The forward-to configuration attribute

The functionality of this attribute is described in full below but in short, add this attribute in with a URL and the user will be forwarded to that page upon the component successfully adding a membership to their basket.

We would recommend using this functionality with either a fail container or using the fail event to provide feedback when there are issues.

Configuration Attributes/Properties

Spektrix web component's initial state is set through attributes placed on the Web Component itself. These values are also accessible as properties on the component. The standard way of working with Web Components is to set the initial state through an attribute on the component then, if you wish to change the state later, changing the value through it's corresponding property.

An example of when you may wish to do with the spektrix-memberships component is setting the membershipId property through javascript, using a slider to change the level of membership (eg - bronze to silver to gold).

client-name

Required: Yes
Type: String
As property: clientName

The clientName is the unique identifier for the client on the Spektrix system. You'll notice them in our iframe addresses and api calls. For example, in the below iframe:

https://system.spektrix.com/thetheatre/website/eventlist.aspx

In this URL, "thetheatre" would be the clientName.

custom-domain

Required: No
Type: String
As property: customDomain

The custom domain if the client is using one (e.g. tickets.thetheatre.org). If they are not using a custom domain, this attribute can be omitted.

membership-id

Required: Yes
Type: String
As property: membershipId

The membershipId is the unique identifier for the membership on the client's Spektrix system. This is the membership that will be posted to the basket.

You can find the ID's for all the memberships on a client's system through our APIv3. The call you would need to make is a GET to:

https://system.spektrix.com/{clientName}/api/v3/memberships

auto-renew

Required: No
Type: boolean
As property: autoRenew

You can use this property to enable memberships to autorenew as the default. Unlike other properties, you add auto-renew on to HTML with no value set. Existence of it equates to true and lack thereof means false.

Note: If no checkbox with data-set-autorenew exists but the membership can auto-renew (as indicated by the API), the component defaults to true. If neither condition is met, it defaults to false.

forward-to

Required: no
Type: String
As property: forwardTo

This attribute unlocks the forward-to functionality of the component. For this component, it will be triggered only once posting the membership has been confirmed as successful.

culture

Required: no
Type: String
As property: culture

The culture/language code used for formatting membership period displays. This can be set on the component or will fall back to the lang attribute on the HTML document. Examples: en, fr, cy, en-ca, fr-ca.

When the culture attribute is changed after initial load, the component will automatically re-render with the new culture settings.

Attributes to place on internal markup which unlock functionality

When the component initialises, it places an event listener on itself which listens to all events which fire from child elements of itself. It will examine each event to see if the element which triggered it has one of the below data-* attributes. If it does, it will perform a predefined action described under each data-* element.

The below lists all the attributes you can add to child elements of the component to unlock it's functionality.

data-submit-membership

Required: yes
Type: boolean

Any element containing this attribute will trigger a request posting the membership to the basket whenever clicked.

<button data-submit-membership>Add to Basket</button>

data-set-autorenew

Required: no
Type: boolean

When placed on a checkbox input, the component will read the checked state of this checkbox at the time of submission to determine whether the membership should auto-renew.

<input type="checkbox" data-set-autorenew>

data-success-container

Required: no, but advisable if not providing feedback for forwardTo or the "success" event Type: boolean

If you place an element in the component that has the attribute data-success-container and one with the data-fail-container and set display none inline on these elements, the component will display or hide these containers based on whether adding memberships to the basket was successful.

<div data-success-container style="display: none;">Insert success content/markup here</div>

data-fail-container

Required: no, but advisable if not providing feedback via the "fail" event Type: boolean

If you place an element in the component that has the attribute data-success-container and one with the data-fail-container and set display none inline on these elements, the component will display or hide these containers based on whether adding memberships to the basket was successful.

<div data-fail-container style="display: none;">Insert failure content/markup here</div>

data-loading-container

Required: no
Type: boolean

An element with this attribute will be shown while the component is loading data from the API and hidden once loading is complete. This element automatically receives aria-busy="true" and role="status" for screen reader accessibility. This is mostly useful when combined with a 'skeleton' which is designed to match the expected size and shape of the loaded component.

<div data-loading-container style="display: block;">Loading...</div>

data-loaded-container

Required: no
Type: boolean

An element with this attribute will be hidden while the component is loading data and shown once loading is complete.

<div data-loaded-container style="display: none;">
<!-- Your content here -->
</div>

Attributes for displaying membership data

The component can fetch membership details from the Spektrix API and populate elements with specific data attributes. Simply add these attributes to elements within your component markup, and the component will update their content when the data is loaded.

data-name

Displays the membership name.

<h2 data-name></h2>

data-description

Displays the plain text description of the membership.

<p data-description></p>

data-html-description

Displays the HTML description of the membership. The content is inserted as HTML, not text.

<div data-html-description></div>

data-price

Displays the membership price (minimum price for variable memberships).

<span data-price></span>

data-renewal-price

Displays the membership renewal price.

<span data-renewal-price></span>

data-max-price

Displays the maximum price for variable value memberships. This will not replace the span if the membership is not variable.

<span data-max-price></span>

data-image-url

When placed on an <img> element, sets the src attribute to the membership's image URL. Also automatically sets the alt attribute if alt text is available from the API.

<img data-image-url style="max-width: 300px;" />

data-thumbnail-url

When placed on an <img> element, sets the src attribute to the membership's thumbnail URL. Also automatically sets the alt attribute if alt text is available from the API.

<img data-thumbnail-url style="max-width: 150px;" />

data-alt-text

When placed on an <img> element, sets only the alt attribute from the membership's alt text. Use this when you have a static image but want dynamic alt text.

<img data-alt-text src="my-static-image.jpg" />

Conditional display attributes

These attributes allow you to show or hide content based on membership properties.

data-can-auto-renew

Shows the element when the membership can auto-renew, hides it otherwise.

<div data-can-auto-renew style="display: none;">
<label>
<input type="checkbox" data-set-autorenew> Enable auto-renewal
</label>
</div>

data-cannot-auto-renew

Shows the element when the membership cannot auto-renew, hides it otherwise.

<div data-cannot-auto-renew style="display: none;">
<p>Auto-renewal is not available for this membership.</p>
</div>

data-is-giftable

Shows the element when the membership is giftable, hides it otherwise.

<div data-is-giftable style="display: none;">
<p>This membership can be purchased as a gift!</p>
</div>

data-is-not-giftable

Shows the element when the membership is not giftable, hides it otherwise.

<div data-is-not-giftable style="display: none;">
<p>This membership cannot be gifted.</p>
</div>

data-is-variable-membership

Shows the element when the membership has variable pricing, hides it otherwise. Use this to display custom price inputs for variable memberships.

<div data-is-variable-membership style="display: none;">
<label>Choose your price:</label>
<input type="number" data-variable-price-input />
</div>

data-is-not-variable-membership

Shows the element when the membership has fixed pricing, hides it otherwise.

<div data-is-not-variable-membership style="display: none;">
<p>Price: $<span data-price>0</span></p>
</div>

data-customer-holds-membership

Shows the element when the logged-in customer already owns this membership, hides it otherwise. Requires the customer to be logged in for this to work correctly.

<div data-customer-holds-membership style="display: none;">
<p>You're already a member! Thank you for your support.</p>
</div>

data-customer-does-not-hold-membership

Shows the element when the logged-in customer does not own this membership, hides it otherwise.

<div data-customer-does-not-hold-membership style="display: none;">
<button data-submit-membership>Become a Member</button>
</div>

Variable value memberships

For memberships configured with variable pricing in Spektrix, customers can choose their own price within defined minimum and maximum bounds.

data-variable-price-input

Place this attribute on an <input> element to capture the customer's chosen price. The component automatically sets min and max attributes on number and range inputs based on the membership's price bounds.

When multiple inputs have this attribute, the component reads the value from the first one found. You can use multiple inputs (e.g., a slider and a number input) with JavaScript to synchronize their values.

<!-- Range slider -->
<input type="range" data-variable-price-input />

<!-- Number input -->
<input type="number" data-variable-price-input />

If the customer enters a value outside the allowed range, the component will automatically clamp the value to the minimum or maximum price when submitting.

If no value is entered, the component will use the membership's base price (minimum).

Membership period display

The component can display membership period information using customizable format strings that support multiple languages.

data-membership-period

Place this attribute on an element to display the formatted membership period. Use additional data-period-format-* attributes to define the format for each expiry type.

Format tokens:

  • {years} - Number of years
  • {months} - Number of months
  • {weeks} - Number of weeks
  • {days} - Number of days

Expiry types:

  • yearsmonthsdays - Period defined in years, months, and days
  • weeksdays - Period defined in weeks and days
  • fixed - Fixed expiry date (use static text)
  • openended - Never expires (use static text)

Basic example:

<span data-membership-period 
data-period-format-yearsmonthsdays="{years} year(s) and {months} month(s)"
data-period-format-weeksdays="{weeks} week(s) and {days} day(s)"
data-period-format-fixed="Valid until a fixed date"
data-period-format-openended="Lifetime membership">
</span>

Multi-language example:

Add a culture suffix to provide translations. The component will use culture-specific formats when the culture attribute matches:

<span data-membership-period 
data-period-format-yearsmonthsdays="{years} year(s) and {months} month(s)"
data-period-format-yearsmonthsdays-fr="{years} an(s) et {months} mois"
data-period-format-yearsmonthsdays-cy="{years} blwyddyn/blynyddoedd a {months} mis/misoedd"
data-period-format-weeksdays="{weeks} week(s) and {days} day(s)"
data-period-format-weeksdays-fr="{weeks} semaine(s) et {days} jour(s)"
data-period-format-weeksdays-cy="{weeks} wythnos/wythnosau a {days} diwrnod/diwrnodau">
</span>

Culture resolution:

  1. First, the component checks for the culture attribute on the component itself
  2. If not found, it falls back to the lang attribute on the <html> element
  3. If a culture-specific format (e.g., data-period-format-yearsmonthsdays-fr) is found, it's used
  4. Otherwise, the default format (e.g., data-period-format-yearsmonthsdays) is used

Supported culture code formats:

  • Simple: en, fr, cy, de
  • Regional with hyphen: en-us, en-ca, fr-ca
  • Regional with underscore: en_us, en_ca, fr_ca

Culture codes are case-insensitive.

Complete example

Here's a comprehensive example showing many features working together:

<spektrix-memberships 
client-name="thetheatre"
membership-id="1213ANPPNPTJDSBPNJDDPKRNVDCBQQRDC"
forward-to="https://tickets.thetheatre.org/checkout"
culture="en">

<!-- Loading state -->
<div data-loading-container style="display: block; text-align: center; padding: 2em;">
<p>Loading membership details...</p>
</div>

<!-- Loaded content -->
<div data-loaded-container style="display: none;">
<h2 data-name>Membership Name</h2>
<img data-image-url style="max-width: 300px;" />
<div data-html-description></div>

<!-- Membership period -->
<p>
<strong>Duration:</strong>
<span data-membership-period
data-period-format-yearsmonthsdays="{years} year(s), {months} month(s)"
data-period-format-weeksdays="{weeks} week(s), {days} day(s)"
data-period-format-fixed="Until a fixed date"
data-period-format-openended="Lifetime">
</span>
</p>

<!-- Already a member -->
<div data-customer-holds-membership style="display: none; background: #d4edda; padding: 1em;">
<h3>You're Already a Member!</h3>
<p>Thank you for your continued support.</p>
</div>

<!-- Not a member -->
<div data-customer-does-not-hold-membership style="display: none;">

<!-- Fixed price membership -->
<div data-is-not-variable-membership style="display: none;">
<p><strong>Price:</strong> $<span data-price>0</span></p>
<p><strong>Renewal:</strong> $<span data-renewal-price>0</span></p>
</div>

<!-- Variable price membership -->
<div data-is-variable-membership style="display: none;">
<p>Choose your membership amount:</p>
<p>
Between $<span data-price>0</span> and $<span data-max-price>0</span>
</p>
<input type="range" data-variable-price-input style="width: 100%;" />
<input type="number" data-variable-price-input placeholder="Or enter amount" />
</div>

<!-- Auto-renew option (only shown if available) -->
<div data-can-auto-renew style="display: none;">
<label>
<input type="checkbox" data-set-autorenew checked> Auto-renew my membership
</label>
</div>

<button data-submit-membership>Purchase Membership</button>
</div>
</div>

<!-- Feedback containers -->
<div data-success-container style="display: none; background: #d4edda; padding: 1em;">
Success! Redirecting to checkout...
</div>
<div data-fail-container style="display: none; background: #f8d7da; padding: 1em;">
Something went wrong. Please try again.
</div>
</spektrix-memberships>