Developer guide
How the gallery is built, and how to render it, override its templates, read its settings and extend it from a theme or plugin.
Architecture
| Free | Pro | |
|---|---|---|
| Namespace | Siteryn\SiterynProductGalleryZoom | Siteryn\SiterynProductGalleryZoomPro |
| Text domain | siteryn-product-gallery-zoom | siteryn-product-gallery-zoom-pro |
| Boot | plugins_loaded, then fires siteryn_pgz_loaded | On siteryn_pgz_loaded, then fires siteryn_pgz_pro_loaded |
| Settings option | siteryn_pgz_settings | siteryn_pgz_pro_settings |
On init (priority 20), when Enable Product Gallery is on, Free removes woocommerce_show_product_images from woocommerce_before_single_product_summary, adds its own renderer at priority 20, returns false for WooCommerce's zoom, PhotoSwipe and FlexSlider filters, and filters the woocommerce/product-image-gallery block output. Pro extends Free only through hooks: it swaps the template for the selected style and, when licensed, loads its own assets instead of Free's.
Rendering the gallery
siteryn_pgz_product_gallery( int $product_id = 0 ): void // 0 = current product
The template tag and [siteryn_pgz_gallery] render the markup but don't load assets; Free enqueues its CSS and JS only on single product pages. Elsewhere, enqueue them yourself:
\Siteryn\SiterynProductGalleryZoom\Assets::enqueue_gallery_assets(); siteryn_pgz_product_gallery( 123 ); // or echo do_shortcode( '[siteryn_pgz_gallery id="123"]' ); // Pro (licensed): style shortcodes enqueue their own assets and accept Free settings as attributes. echo do_shortcode( '[siteryn_pgz_pro_grid id="123" main_image_fit="cover" zoom_mode="lens"]' );
A Pro style rendered through Free's path off a product page also needs \Siteryn\SiterynProductGalleryZoomPro\Assets::enqueue_style_assets( 'grid' ).
Useful public methods
| Method | Returns |
|---|---|
Frontend::get_gallery_html( $product ) | The gallery HTML, or '' for an invalid product |
Gallery::get_images( $product ) | The image list passed to the template |
Settings::get_all() · Settings::get( $key ) · Settings::defaults() | Free settings merged over defaults |
Templates::get_template_html( $name, $args ) · Templates::locate( $name ) | Rendered template · resolved path |
Pro License::is_active() | Whether the Pro license is valid |
Pro VideoMeta::get_videos( $product ) | A product's videos |
Free classes live in Siteryn\SiterynProductGalleryZoom, Pro classes in Siteryn\SiterynProductGalleryZoomPro.
Templates
Copy templates/product-image.php from the Free plugin to your-theme/siteryn-product-gallery-zoom/product-image.php. It receives $product, $images and $settings. Keep the @version header: when the bundled copy has a newer version, administrators see "Siteryn Product Gallery template files should be updated".
id, alt, full_src, full_srcset, full_sizes, full_width, full_height, // main image (woocommerce_gallery_image_size) thumb_src, thumb_width, thumb_height, // thumbnail (woocommerce_gallery_thumbnail_size) lightbox_src, lightbox_width, lightbox_height // zoom & lightbox (woocommerce_gallery_full_size)
The product image comes first, then the gallery images, without duplicates. A product without images gets one placeholder item with id 0.
siteryn_pgz_pro_style_templates filter.
add_filter( 'siteryn_pgz_pro_style_templates', function ( $templates ) {
$file = locate_template( 'siteryn-product-gallery-zoom-pro/style-grid.php' );
if ( $file ) {
$templates['grid'] = $file;
}
return $templates;
}, 20 );
Keep namespace Siteryn\SiterynProductGalleryZoomPro; at the top of the copy. The vertical-slider, vertical-scroll and multirow-slider templates also include a file from parts/; copy it alongside.
Markup contract
The script finds the gallery through these attributes; keep them in a template override.
| Part | Selector |
|---|---|
| Root | div.images.woocommerce-product-gallery.siteryn-pgz-gallery[data-siteryn-pgz-gallery], with .siteryn-pgz-gallery--thumbs-{bottom|top}, .siteryn-pgz-gallery--transition-{type} and data-arrow-placement, data-arrow-alignment, data-main-transition, data-zoom-mode, data-zoom-lens-shape, data-zoom-window-position; the script sets data-current-index |
| Slides | [data-siteryn-pgz-track] > .siteryn-pgz-gallery__slide[data-index][data-image-id], image img.siteryn-pgz-gallery__main-image[data-zoom-src] |
| Lightbox trigger | button[data-siteryn-pgz-lightbox-trigger] |
| Arrows | [data-siteryn-pgz-prev] · [data-siteryn-pgz-next] (.siteryn-pgz-gallery__arrow; inside .siteryn-pgz-gallery__arrow-row--above|--below for those placements) |
| Thumbnails | [data-siteryn-pgz-thumbs] > button.siteryn-pgz-gallery__thumb[data-index] (active: .is-active), inside .siteryn-pgz-gallery__thumbs-wrap; scroll buttons [data-siteryn-pgz-thumb-prev] · [data-siteryn-pgz-thumb-next] |
| Lightbox | [data-siteryn-pgz-lightbox] (data-keyboard, data-touch, data-slideshow-interval), moved to <body>; html.siteryn-pgz-lightbox-open while open |
| Lightbox parts | [data-siteryn-pgz-lightbox-image], -close, -prev, -next, -counter, -thumbs, and toolbar -zoom, -share, -slideshow (all data-siteryn-pgz-lightbox-…) |
JavaScript
- Script handle
siteryn-pgz, in the footer, with no jQuery dependency; style handlesiteryn-pgz(depends ondashicons). Minified files load unlessSCRIPT_DEBUGis on. - The only localized data is
siterynPgz.i18n.counterFormat(%1$s / %2$s). - There is no public JavaScript API and no custom events. Galleries initialise once, on
DOMContentLoaded(or straight away if the page has already loaded). - To go to an image, click its thumbnail:
gallery.querySelector('.siteryn-pgz-gallery__thumb[data-index="2"]').click(). - Variation switching listens to WooCommerce's
found_variationandreset_dataevents (needs jQuery) on the page's first variations form. - Galleries loaded later by AJAX (quick views) aren't initialised, and running the script again double-binds existing galleries.
CSS custom properties
Your settings are printed as an inline style on :root (tablet and mobile overrides in max-width: 782px and 480px media queries). Override them in your theme to restyle the gallery without a template.
| Part | Variables (--siteryn-pgz-…) |
|---|---|
| Main image | main-bg, main-ratio, main-fit, main-border-width, main-border-color, main-radius, main-spacing, main-transition, main-transition-speed |
| Thumbnails | thumb-ratio, thumb-spacing, thumb-visible-count, thumb-radius, thumb-active-color, thumb-active-width, thumb-inactive-opacity; the script sets thumb-effective-count on the strip |
| Arrows | arrow-size, arrow-icon-size, arrow-radius, arrow-bg, arrow-icon-color, arrow-border-width, arrow-border-color, arrow-hover-bg, arrow-hover-icon-color, arrow-offset, arrow-shadow |
| Lightbox | lightbox-bg, lightbox-fit, lightbox-max-width, lightbox-icon-color, lightbox-icon-bg |
| Zoom | zoom-inner-scale, zoom-lens-size, zoom-lens-scale, zoom-lens-border-width, zoom-lens-border-color, zoom-window-width, zoom-window-scale, zoom-window-border-width, zoom-window-border-color |
The zoom layers the script adds are .siteryn-pgz-zoom-inner, .siteryn-pgz-zoom-lens and .siteryn-pgz-zoom-window (each .is-active while showing).
Data
| Name | Type | Content |
|---|---|---|
siteryn_pgz_settings | Option | All Free settings (81 keys) |
siteryn_pgz_version | Option | Installed Free version |
siteryn_pgz_pro_settings · siteryn_pgz_pro_version | Option | Pro style settings (gallery_style plus per-style keys) · version |
siteryn_license_product-gallery-zoom_key · _status · _update | Option | Pro license key, cached status, update info (not autoloaded) |
_siteryn_pgz_pro_videos | Post meta | A product's videos: [{url, thumb_id}] |
_siteryn_pgz_pro_videos_auto_thumbs | Post meta | Automatic YouTube/Vimeo thumbnails, keyed by URL |
_siteryn_pgz_pro_video_url · _siteryn_pgz_pro_video_thumb_id · _siteryn_pgz_pro_video_thumb_auto_url | Post meta | Older single-video format: read only when _siteryn_pgz_pro_videos is missing, and removed the next time the product is saved with an active license |
siteryn_pgz_outdated_templates | Transient | Outdated template check, 1 day |
update_post_meta( $product_id, '_siteryn_pgz_pro_videos', array( array( 'url' => 'https://www.youtube.com/watch?v=XXXXXXXXXXX', 'thumb_id' => 0 ), array( 'url' => 'https://example.com/media/demo.mp4', 'thumb_id' => 789 ), ) );
Video URLs can be self-hosted .mp4, .webm or .ogv files, or anything WordPress can embed. Settings keys are listed per tab on the feature pages; for example zoom_mode is none, inner, lens or window.
Uninstalling Free deletes its two options (on every site of a network). Uninstalling Pro deletes its options and license data; product videos are kept.
Endpoints
There are no REST routes, blocks or public AJAX actions. Admin endpoints require manage_woocommerce and a nonce:
| Action | Used for |
|---|---|
wp_ajax_siteryn_pgz_save_settings | Saving a settings tab |
admin_post_siteryn_pgz_reset_settings · admin_post_siteryn_pgz_pro_reset_settings | Reset to Defaults |
wp_ajax_siteryn_pgz_pro_license_action | Activating or deactivating the Pro license |
wp_ajax_siteryn_deactivation_feedback (shared by Siteryn plugins) sends the optional deactivation survey; it requires activate_plugins and a nonce.
There are no cron events and no custom capabilities.
wp-config constants
| Constant | Effect |
|---|---|
SCRIPT_DEBUG | Load unminified CSS and JS |
SITERYN_FEEDBACK_ENDPOINT | Where the optional deactivation survey is sent (shared by Siteryn plugins; also filterable with siteryn_deactivation_feedback_endpoint) |
SITERYN_PGZ_PRO_LICENSE_API_BASE | License server URL (default https://siteryn.com/wp-json/siteryn/v1), e.g. for staging |
Hooks and their examples are on Hooks & filters.