Hello everyone, I am currently working on Wix Studio to create a radio website.
I would like to use an audio player to let the user listen to the radio music while exploring the website.
I used an iframe to create my audio player (because we can’t change the height of the default one)
The issue is that with this method the iframe loads each time when I switch to another page. Then the music player stop and the user has to click again on “play” to resume.
However I already manage to create this on the old version of Wix with the “display on every pages” toggle.
I just wanted to know if this was possible on Wix Studio.
Thanks in advance for your help!
Ahhh this is a fun one! I recently solved this for a small personal project I was working on, so hopefully can point you in the right direction.
Here goes 
You’ll need
- A master section (I personally used a header)
- A custom element (This is where the radio stream will be run from)
- A button (To control the play/pause of the radio stream)
Code needed
masterPage.js code:
import { local } from "wix-storage-frontend";
$w.onReady(function () {
// Retrieve the current playing state from local storage.
let isPlaying = local.getItem("isPlaying");
// If no state exists yet, initialize it to "false".
if (isPlaying === null) {
isPlaying = "false";
local.setItem("isPlaying", isPlaying);
}
// Add a click event listener to the play/pause button.
$w("#heroPlayBtn").onClick(() => {
// Toggle the playing state: if it's "true", change to "false", and vice versa.
let newState = local.getItem("isPlaying") === "true" ? "false" : "true";
local.setItem("isPlaying", newState);
// Update the custom element's "playing" attribute so that it can react accordingly.
$w("#customElement1").setAttribute("playing", newState);
});
});
Custom element:
class StreamPlayer extends HTMLElement {
constructor() {
super();
// Attach a shadow DOM to encapsulate the element's internals.
this.attachShadow({ mode: "open" });
// Use a global shared audio instance to prevent overlapping streams.
if (!window.__sharedAudio) {
// If it doesn't exist, create a new Audio instance with the default stream source.
window.__sharedAudio = new Audio("https://media-ssl.musicradio.com/ClassicFMMP3");
}
// Reuse the shared audio instance.
this.audio = window.__sharedAudio;
// Set the initial playing state based on whether the shared audio is currently playing.
this.isPlaying = !this.audio.paused;
// Check local storage to determine if the stream should resume playback after navigation.
const storedState = localStorage.getItem("isPlaying");
if (storedState === "true" && this.audio.paused) {
this.play();
}
}
// Specify the attributes to observe for changes.
static get observedAttributes() {
return ["stream", "playing"];
}
// Handle changes to observed attributes.
attributeChangedCallback(name, oldValue, newValue) {
if (name === "stream" && newValue) {
// If the stream URL changes, update the audio source.
this.audio.src = newValue;
}
if (name === "playing") {
console.log(`Attribute changed: playing=${newValue}`);
// Start or stop the stream based on the new "playing" attribute value.
if (newValue === "true") {
this.play();
} else {
this.pause();
}
}
}
// Method to start playing the audio.
play() {
// Avoid playing if no source is set or if the audio is already playing.
if (!this.audio.src || !this.audio.paused) return;
// Start the audio playback.
this.audio.play()
.then(() => {
// Update the playing state and store it in local storage.
this.isPlaying = true;
localStorage.setItem("isPlaying", "true");
// Dispatch a custom event to notify listeners that playback has started.
this.dispatchEvent(new CustomEvent("playing", { detail: { playing: true } }));
})
.catch(console.error);
}
// Method to pause the audio.
pause() {
// Do nothing if the audio is already paused.
if (this.audio.paused) return;
console.log("Pause function called");
// Pause the audio stream.
this.audio.pause();
this.isPlaying = false;
localStorage.setItem("isPlaying", "false");
// Dispatch a custom event to notify listeners that playback has paused.
this.dispatchEvent(new CustomEvent("playing", { detail: { playing: false } }));
}
}
// Define the custom element, so it can be used in your page.
customElements.define("stream-player", StreamPlayer);
Both the button and the custom element will be in the header - the button will send a message to the custom element that tells it to play or pause. And it should continue it’s playing across page navigation 
You’ll need to change a few things out, such as element IDs, and your stream URL (I added Classic FM for this demo) - and hopefully this will get you on your way. Good luck!
Hello Noah,
Thank you for your assistance. I followed your instructions and adapted your code to my own project. However, it appears that the custom element feature is only active on the webpage when using a Wix Studio premium plan.
I currently have a premium plan for the standard Wix version. Is it possible to convert my existing plan to a Wix Studio plan?
I also have two more questions:
-
Is there an alternative to using a custom element to create a site-wide player that’s accessible on every page?
-
Can the player be placed in a preloaded footer?
Thank you in advance for your help, and I look forward to your response.
Best regards,