> ## Documentation Index
> Fetch the complete documentation index at: https://cloudinary.com/documentation/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrating from Cloudinary 3D to the Product Gallery widget viewer


> **INFO**:
>
> **Cloudinary 3D viewer and AR capabilities are transitioning to the Product Gallery Widget.** Cloudinary 3D remains available through Q1 2026 to support your move.

## Introduction

This page explains how to migrate from the Cloudinary 3D viewer to the Product Gallery widget viewer.

In addition, see the [Product Gallery API reference](product_gallery_reference) and [guide](product_gallery#3d_models) to become familiar with its capabilities.

## Typical configuration

This is a typical Product Gallery widget configuration:

```js
const myWidget = cloudinary.galleryWidget({
 cloudName: 'demo', // your Cloudinary cloud name
 container: '#my-gallery',
 carouselStyle: 'none',
 ar3dProps: {
   showAR: true,
   showZoomButtons: true,
   useCustomArModal: true,
 },
 mediaAssets: [
   { publicId: "docs/3d/red_sneaker", mediaType: "3d" },
   // "publicId" replaces "sku" used to identify the 3D model file
   // mediaType: "3d" is mandatory for 3D models
 ]
});
```

 
 
   
     AR Instructions
     Scan this QR code with your mobile device to view in AR
     
     
     Close
   
 

> **NOTE**: The 3D model file identifier is now its Cloudinary public ID, not Cloudinary 3D's SKU, as shown in the example above under the `mediaAssets` property.

## Viewer events

> **TIP**: Learn about [Product Gallery widget events](product_gallery_reference#events).

The events relevant to the 3D viewer experience are:

* **3dmodelloaded**: Fired once the model has finished loading.
* **onQrReady**: Fired once the QR code and URL for the AR viewer are ready. The payload includes the QR SVG and the URL string.
* **onArClick**: Fired when the user clicks the native **view in AR** button.

## Customization examples

### Custom AR modal

Use a custom AR modal to display the QR code but keep the native "view in AR" button:

```js
window.addEventListener('load', () => {
 const myWidget = cloudinary.galleryWidget({
   cloudName: 'demo',
   container: '#my-gallery',
   debug: true,
   carouselStyle: 'none',
   ar3dProps: {
     showAR: true,
     useCustomArModal: true, // This property stops the default modal from showing
   },
   mediaAssets: [
     { publicId: 'docs/3d/red_sneaker', mediaType: '3d' }
   ]
 });

myWidget.on('onArClick', (e) => { // Use this event to show your custom modal
  const { qrUrl, qrSvg } = e.data;
  const modal = document.getElementById('ar-modal'); // Your custom modal element
  const qrContainer = document.getElementById('ar-qr-code');
  const urlContainer = document.getElementById('ar-url');

  qrContainer.innerHTML = qrSvg;
  urlContainer.innerHTML = `<a href="${qrUrl}" target="_blank">${qrUrl}</a>`;
  modal.style.display = 'flex';

  document.getElementById('close-modal').onclick = () => {
    modal.style.display = 'none';
  };
});

myWidget.render();
});
```

HTML template:

```html
<div class="gallery-container" style="position: relative;">
 <div id="my-gallery"></div>
 <div id="ar-modal" class="modal-overlay" style="display: none;">
   <div class="modal-content">
     <h2>AR Instructions</h2>
     <p>Scan this QR code with your mobile device to view in AR</p>
     <div id="ar-qr-code"></div>
     <div id="ar-url" class="ar-url"></div>
     <button id="close-modal">Close</button>
   </div>
 </div>
</div>
```

 
 
   
     AR Instructions
     Scan this QR code with your mobile device to view in AR
     
     
     Close
   
 

### Custom AR button and AR modal

Use a custom "view in AR" button and a custom AR modal to display the QR code: 

```js
window.addEventListener('load', () => {


 const myWidget = cloudinary.galleryWidget({
   cloudName: 'demo',
   container: '#my-gallery',
   carouselStyle: 'none',
   ar3dProps: {
     showAR: false, // Hides the native "view in AR" button
   },
   mediaAssets: [
     { publicId: "docs/3d/red_sneaker", mediaType: "3d" },
   ]
 });


 myWidget.on('onQrReady', (e) => {
   const { qrSvg, qrUrl } = e.data;
   const customArButton = document.getElementById('custom-ar-button');
   customArButton.onclick = () => {
     const modal = document.getElementById('ar-modal');
     const qrContainer = document.getElementById('ar-qr-code');
     const urlContainer = document.getElementById('ar-url');


     qrContainer.innerHTML = qrSvg;
     urlContainer.innerHTML = `<a href="${qrUrl}" target="_blank">${qrUrl}</a>`;
     modal.style.display = 'flex';


     document.getElementById('close-modal').onclick = () => {
       modal.style.display = 'none';
     };
   };
 });


 myWidget.render();
});
```

HTML template:

```html
<div class="gallery-container" style="position: relative;">
 <div id="my-gallery"></div>
 <div id="ar-modal" class="modal-overlay" style="display: none;">
   <div class="modal-content">
     <h2>AR Instructions</h2>
     <p>Scan this QR code with your mobile device to view in AR</p>
     <div id="ar-qr-code"></div>
     <div id="ar-url" class="ar-url"></div>
     <button id="close-modal">Close</button>
   </div>
 </div>
</div>
```

 
 View in AR
 
   
     AR Instructions
     Scan this QR code with your mobile device to view in AR
     
     
     Close
   
 

