copyToClipboard not working in Mobile Browser

Anyone encounter wixWindow.copyToClipboard not working in Mobile Browser?
I implement click button to copy to clipboard, it works on PC Browser, but when I test on mobile browser, it just show popup and with the text that supposed to copy, with OK & Cancel. When click OK, the popup closed. Nothing was copied, I can’t paste anything from it.

I’ve google a lot, but unable to find the solution, even the site that has this guide ( https://codequeen.wixsite.com/copy-to-clipboard ), are not working when I test on mobile browser.

This is not your fault. This is a known issue happened a long time ago. @Yiserel, can you pass this to the components team? I think it is the iOS blocking the copy to clipboard access

This has been reported.

Issues with wixWindow.copyToClipboard on Safari iOS – Seeking Solutions

I’m experiencing problems with the Wix “copyToClipboard()” function (Copy To Clipboard | Velo) on my Wix website when using Safari on iOS devices. While the function works perfectly on desktop browsers like Chrome and Edge, it doesn’t function correctly on Safari for iOS. Users are either seeing a Copy to clipboard dialog or the copying fails silently, which negatively impacts the user experience.

Attempts to Resolve:

  1. Using navigator.clipboard.writeText:
  • Not viable because direct access to navigator.clipboard is restricted in the Wix Velo environment.
  1. Using document.execCommand('copy') within an HTML Component:
  • Direct access to the global document object is not allowed in Wix Velo.
  • Embedding HTML components (iframes) doesn’t solve the issue due to security restrictions in Safari.
  1. External NPM Packages like copy-to-clipboard or clipboard-js:
  • These packages either don’t function correctly within the Wix environment or don’t resolve the issue on Safari iOS.
  1. Alternative Approaches:
  • Automatically selecting the promo code in an input field to facilitate manual copying. The “select” function is not working.

Possible Causes:

  • Safari iOS Security Restrictions:
    • Strict security policies prevent automatic clipboard copying without direct user interaction.
    • Even with user interaction, Safari may display a confirmation dialog that cannot be suppressed.
  • Wix Velo Limitations:
    • Restricted access to global objects like document and navigator.clipboard.
    • This limits the ability to implement alternative copying methods.

Request for Assistance:

  • Is there a way to modify or extend the wixWindow.copyToClipboard function to work reliably on Safari iOS without triggering a confirmation dialog?
  • Could Wix update the internal implementation of copyToClipboard to utilize the latest clipboard APIs supported by Safari on iOS, or provide alternative methods compatible with Apple’s security policies?
  • Are there any known workarounds or best practices to overcome this issue without degrading the user experience?
  • Many modern websites use the navigator.clipboard.writeText() API to reliably copy text to the clipboard, which works seamlessly across browsers, including Safari on iOS, as long as it’s triggered by a user interaction like a button click. I would like to request the implementation of support for the modern Clipboard API (navigator.clipboard.writeText) in Wix Velo.

Goal:

I aim to provide a seamless experience where users can copy a promo code by clicking a button, across all major browsers and devices, including Safari on iOS.

Any insights or suggestions would be greatly appreciated.

Best regards and thank you in advance!

Hi Do you have any solutions on this Topic? I have the same problem :frowning:

Here in 2026 and just ran into this issue as well. I tried a workaround using Embedded Code and it works!

  1. From Wix Editor: Add Element → Embed Code → Custom element
  2. Click on the inserted custom element and click “Choose Source”.
  3. Choose “Velo file”
  4. Select one of your Velo files: e.g. copy-to-clipboard-button.js
    • If it’s your first custom element it will prompt you to create your first file which ends up in Backend & Public → Public → custom-elements/
  5. Tag name: e.g. copy-to-clipboard-button

In copy-to-clipboard-button.js

class CopyToClipboardButton extends HTMLElement {
    connectedCallback() {
        const shadow = this.attachShadow({ mode: 'open' });
        const button = document.createElement('button');
        this._button = button;
        button.textContent = 'Copy Text';
        button.addEventListener('click', () => {
          navigator.clipboard.writeText('Well I guess the text was copied successfully');
        });

        shadow.append(button);
    }
}
customElements.define('copy-to-clipboard-button', CopyToClipboardButton);

Have to do a little more work to support setting the clipboard value from Velo as well as styling the button. I will update this reply when I figure it out.

Here’s the rest of the solution. This allows you to programmatically set the text you want to copy to clipboard from within Velo code.

// copy-to-clipboard-button.js
class CopyToClipboardButton extends HTMLElement {
    // This exposes a "text" attribute to Velo
    static get observedAttributes() {
        return ['text'];
    }

    // This is for replacing the click handler when the attribute changes
    _attachClickHandler() {
        if (this._button && this._clickHandler) {
            this._button.removeEventListener('click', this._clickHandler);
        }
        if (this._button) {
            this._clickHandler = () => {
                // Set the value in the clipboard
                navigator.clipboard.writeText(this._text || '');
                this._button.textContent = 'Copied!';
            }
            this._button.addEventListener('click', this._clickHandler);
        }
    }

    // This function gets called when Velo sets the attribute value
    attributeChangedCallback(name, oldValue, newValue) {
        // Only do this is the "text" attribute is updated
        if (name === 'text') {
            this._text = newValue;
            this._attachClickHandler();
        }
    }

    connectedCallback() {
        const shadow = this.attachShadow({ mode: 'open' });
        const button = document.createElement('button');
        this._button = button;
        button.textContent = 'Copy Text';
        
        this._attachClickHandler();

        shadow.append(button);
    }
}
customElements.define('copy-to-clipboard-button', CopyToClipboardButton);
// In your page code
$w.onReady(function () {
    $w('#copyUrlToClipboardButton').setAttribute('text', 'I am the text that will be copied to clipboard');
};

Above works for me but as I was writing this up, it occurred to me that we probably don’t need to replace the click handler every time text changes. This should work but I haven’t tested it out so I’m putting out both implementations.

// copy-to-clipboard-button.js
class CopyToClipboardButton extends HTMLElement {
    // this replaces _attachClickHandler
    clickHandler() {
        navigator.clipboard.writeText(this._text || '');
        this._button.textContent = 'Copied!';
    }

    connectedCallback() {
        // ... all the other stuff

        // This just attaches the above function as a click handler.
        // We need to "bind" `this` so that the above function can reference `this._text`.
        this._button.addEventListener('click', this.clickHandler.bind(this));
    }