Alchemy boasts a sharp and clean design aimed at empowering merchants to create a Shopify store that exudes a strong brand appeal. Rebuilt using web components, it offers a highly modular architecture that makes customisation and maintenance both easier and more versatile than ever before.
In addition, Alchemy is optimized for speed, ensuring stores run as fast as possible to provide customers with a seamless shopping experience.
Caution
The following guide is not intended as general user guidance. It is important to note that we do not offer general support on any custom development to our themes, or provide assistance on leveraging any of the items outlined below.
Custom JavaScript events
Alchemy broadcasts many custom events for ease of extensibility, detailed in this section.
If you would like to add your own JS to Alchemy, we recommend using the custom.js file supplied with the theme and referencing it using Theme settings > Advanced > Custom HTML.
As a brief overview, Alchemy:
- Broadcasts many JS events
- Is built using web components
- Follows a code splitting architecture
- Is completely custom built (no JS libraries)
- Has a number of JS utilities
Events are named in the following convention:
[on/dispatch]:[subject]:[action]
Where dispatch will trigger an event to occur and on indicates an event has occurred.
All return data detailed in this section is returned within the event.detail object.
Tip: When in the Theme Editor, the details of each custom event will be logged out in the Dev Tools console every time one is triggered.
The available events are:
on:variant:change
on:cart:add
on:cart:error
on:line-item:change
on:cart-drawer:before-open
on:cart-drawer:after-open
on:cart-drawer:after-close
on:quickbuy:before-open
on:quickbuy:after-open
on:quickbuy:after-close
dispatch:cart-drawer:open
dispatch:cart-drawer:refresh
dispatch:cart-drawer:close
on:debounced-resize
on:breakpoint-change
on:variant:change
Fires whenever a variant is selected (e.g. product page, quick buy, featured product etc).
How to listen:
document.addEventListener('on:variant:change', (event) => {
// your code here
});
Returned data:
- form: the product form content
- variant: the selected variant object
- product: the product object (includes a list of all variants)
on:cart:add
Fires when a variant has been added to the cart, where it didn’t exist in the cart before. This event does not fire when the added variant was already in the cart. To listen for this, see the on:line-item:change event.
How to listen:
document.addEventListener('on:cart:add', (event) => {
// your code here
});
Returned data:
- cart: the new cart object after the variant was added
- variantId: id of the variant that was just added to the cart
on:line-item:change
Fires when the quantity of an item already in the cart is updated. Note, if the newQuantity is 0, this indicates the item was removed from that cart.
Note, when adding a variant to the cart - this event will fire if that variant is already in the cart (i.e. the quantity is incremented). In this situation, on:cart:add will not fire.
How to listen:
document.addEventListener('on:line-item:change', (event) => {
// your code here
});
Returned data:
- cart: the new cart object after the quantity change was completed
- variantId: id of the variant that was just updated
- newQuantity: new quantity of the line item
- oldQuantity: old quantity of the line item
on:cart:error
Fires when an action related to the cart has failed, for example adding too much quantity of an item to the cart.
How to listen:
document.addEventListener('on:cart:error', (event) => {
// your code here
});
Returned data:
- error: the error message
on:cart-drawer:before-open
Fires before the cart drawer opens.
How to listen:
document.addEventListener('on:cart-drawer:before-open', (event) => {
// your code here
});
on:cart-drawer:after-open
Fires after the cart drawer has finished opening.
How to listen:
document.addEventListener('on:cart-drawer:after-open', (event) => {
// your code here
});
on:cart-drawer:after-close
Fires after the cart drawer has finished closing.
How to listen:
document.addEventListener('on:cart-drawer:after-close', (event) => {
// your code here
});
on:quickbuy:before-open
Fires before the quick buy drawer opens.
How to listen:
document.addEventListener('on:quickbuy:before-open', (event) => {
// your code here
});
on:quickbuy:after-open
Fires after the quick buy drawer has finished opening.
How to listen:
document.addEventListener('on:quickbuy:after-open', (event) => {
// your code here
});
on:quickbuy:after-close
Fires after the quick buy drawer has finished closing.
How to listen:
document.addEventListener('on:quickbuy:after-close', (event) => {
// your code here
});
dispatch:cart-drawer:open
Opens the cart drawer (if enabled in the theme settings).
How to trigger:
document.dispatchEvent(new CustomEvent('dispatch:cart-drawer:open'));
You can optionally pass in a detail object with a property of opener, which specifies the DOM element that should be focussed on when the drawer is closed.
Example:
document.getElementById('header-search').addEventListener('keydown', (evt) => {
if (evt.keyCode === 67) {
evt.preventDefault();
document.dispatchEvent(new CustomEvent('dispatch:cart-drawer:open', {
detail: {
opener: evt.target
}
}));
}
});
In this example, we attach a keydown listener to the search input in the header. If the user presses the c key, it prevents the default behaviour (which would be to type the letter c in the input) and dispatches the dispatch:cart-drawer:open event with a detail object that specifies the search input as the opener. When the cart drawer is closed, focus is returned to the search input.
dispatch:cart-drawer:refresh
Refreshes the contents of the cart drawer.
This event is useful when you are adding variants to the cart and would like to instruct the theme to re-render the cart drawer.
How to trigger:
document.dispatchEvent(new CustomEvent('dispatch:cart-drawer:refresh', {
bubbles: true
}));
dispatch:cart-drawer:close
Closes the cart drawer.
How to trigger:
document.dispatchEvent(new CustomEvent('dispatch:cart-drawer:close'));
on:debounced-resize
Fires when the viewport finishes resizing (debounced to 300ms by default).
How to listen:
window.addEventListener('on:debounced-resize', (event) => {
// your code here
});
on:breakpoint-change
Fires when the breakpoint of the viewport changes. See the Media queries section in this file for more information.
Example:
window.addEventListener('on:breakpoint-change', (event) => {
if (theme.mediaMatches.md) {
console.log(‘we are not on mobile’);
}
});
Web components
Alchemy utilises web components to the fullest.
Web components are a set of standardised APIs that allow developers to create custom, reusable HTML elements that can be used across different web pages and applications. They consist of three main things: custom elements, shadow DOM and HTML Templates.
See the Mozilla Web Component documentation for more.
Code splitting
We followed the ‘code splitting’ technique when building Alchemy.
Code splitting consists of writing in JavaScript (and CSS) in a modularised way within typically small, more manageable files that can be loaded on-demand, as needed. The idea is to improve the performance of our theme by reducing the amount of code that needs to be loaded upfront.
If the customer is visiting a specific page of the theme that requires certain JavaScript functionality, only the code needed for that page will be loaded, rather than one large JavaScript file containing largely unused code. For example, the file media-gallery.js will only be loaded if there is a media gallery on the page.
Shopify uses HTTP/2, which is the newer version of the HTTP protocol used to deliver web content. HTTP/2 supports multiplexing, which means that multiple requests can effectively be sent over a single connection at the same time - meaning multiple JS files are essentially served at the speed of a single file.
The only JS file which is served on every page in Alchemy is main.js. This file contains utility JS which is likely to be needed by many scripts. This is outlined more in the next section.
Media queries
The theme creates a theme.mediaMatches object (defined in theme.liquid) for several key screen sizes specified in our theme, and adds listeners for each media query.
These are:
mediaQueries: {
sm: '(min-width: 640px)',
md: '(min-width: 768px)',
lg: '(min-width: 1024px)',
xl: '(min-width: 1280px)',
xxl: '(min-width: 1536px)',
portrait: '(orientation: portrait)'
}
If a breakpoint is crossed, the mediaMatches values are updated and a on:breakpoint-change event is dispatched.
You can request the entire theme.mediaMatches object to check which media queries are currently matched. In this case, the returned data will be an object with the names of the media queries as keys and boolean values indicating whether they are currently matched or not.
Example:
{
sm: true,
md: true,
lg: true,
xl: true,
xxl: false,
portrait: false
}
You can reference a specific media query to check if it's currently matched by using:
theme.mediaMatches.lg
To check if you’re on mobile you can use:
!theme.mediaMatches.md
If you want to perform some action when the breakpoint changes, you can listen for the breakpoint-change event on the window object.
Example:
window.addEventListener('on:breakpoint-change', (event) => {
// your code here
});
Can't find what you're looking for?
Our support staff are here to answer your queries, so don't hesitate to write to us!
Contact us