{"id":312121,"date":"2026-05-14T08:03:30","date_gmt":"2026-05-14T08:03:30","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/image-hotspots-tool\/"},"modified":"2026-09-23T21:21:29","modified_gmt":"2026-09-23T21:21:29","slug":"pleaseup-hotspots","status":"publish","type":"plugin","link":"https:\/\/brx.wordpress.org\/plugins\/pleaseup-hotspots\/","author":23496860,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"3.1.4","stable_tag":"3.1.4","tested":"7.1.2","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"Image Hotspots by Pleaseup \u2013 Interactive Image Map & Tooltips","header_author":"Pleaseup","header_description":"Add drag &amp; drop hotspots to images from the Media Library, Gutenberg galleries, and ACF fields. Includes a back-office editor and frontend rendering with HTML layers. Use the shortcode to embed hotspot images anywhere.","assets_banners_color":"38c88e","last_updated":"2026-09-23 21:21:29","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/wordpress.org\/plugins\/pleaseup-hotspots\/","header_author_uri":"https:\/\/by.pleaseup.com\/","rating":5,"author_block_rating":0,"active_installs":10,"downloads":456,"num_ratings":1,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"3.0.3":{"tag":"3.0.3","author":"bypleaseup","date":"2026-05-14 09:32:00","revision":3531784},"3.1.0":{"tag":"3.1.0","author":"bypleaseup","date":"2026-05-14 14:51:38","revision":3532160},"3.1.1":{"tag":"3.1.1","author":"bypleaseup","date":"2026-06-16 09:37:24","revision":3574284},"3.1.2":{"tag":"3.1.2","author":"bypleaseup","date":"2026-08-24 09:57:56","revision":3663088},"3.1.3":{"tag":"3.1.3","author":"bypleaseup","date":"2026-09-23 20:45:06","revision":3710156},"3.1.4":{"tag":"3.1.4","author":"bypleaseup","date":"2026-09-23 21:21:29","revision":3710185}},"upgrade_notice":{"3.1.4":"<p>Hotfix for 3.1.3: oEmbed iframes (Vimeo, YouTube, Spotify, SoundCloud) inside tooltips now render correctly again. Update strongly recommended if you use video\/audio embeds in tooltips.<\/p>","3.1.3":"<p>Compatibility refresh for WordPress 7.1 + defense-in-depth hardening of the tooltip render path. No data migration, no breaking changes.<\/p>","3.1.2":"<p>Re-deploy of 3.1.1 (Tested up to WordPress 7.0) after a pipeline race condition shipped stale code under the 3.1.1 tag. No data migration, no breaking changes.<\/p>","3.1.1":"<p>Compatibility refresh: declared support for WordPress 7.0. No data migration, no breaking changes.<\/p>","3.1.0":"<p>Rebrand to &quot;Image Hotspots by Pleaseup&quot; + admin menu label refresh. No data migration, all existing shortcodes (<code>[wphs_image]<\/code>, <code>[wphs_gallery]<\/code>) and settings continue to work.<\/p>","3.0.3":"<p>Distribution hygiene fix: hidden .gitkeep files excluded from the zip; readme tested-up-to bumped to 6.9. No data migration required.<\/p>","3.0.2":"<p>Admin UI strings catch-up rename (&quot;WP Hotspots&quot; \u2192 &quot;Pleaseup Hotspots&quot;). No data migration required.<\/p>","3.0.1":"<p>Rename + asset cleanup for WordPress.org Plugin Directory submission. No data migration required.<\/p>","3.0.0":"<p>Initial release.<\/p>"},"ratings":{"1":0,"2":0,"3":0,"4":0,"5":1},"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3532106,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3532106,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3532106,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3532106,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["3.0.3","3.1.0","3.1.1","3.1.2","3.1.3","3.1.4"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3532145,"resolution":"1","location":"assets","locale":"","width":1920,"height":1603}},"screenshots":{"1":"Plugin admin overview \u2014 image hotspot collections listed in the WordPress back-office.","2":"<strong>Drag &amp; drop editor<\/strong> \u2014 add, move, and delete hotspots visually in the WordPress back-office.","3":"<strong>HTML tooltip layers<\/strong> \u2014 each hotspot opens a fully customisable HTML layer (supports the built-in WP editor).","4":"<strong>Media Library integration<\/strong> \u2014 works with any image already uploaded to WordPress.","5":"<strong>Elementor compatible<\/strong> \u2014 drop the built-in Elementor Shortcode widget on any page and paste <code>[wphs_image id=\"X\"]<\/code>. Works with Elementor free \u2014 no Pro licence required, no add-on needed.","6":"<strong>Gutenberg gallery support<\/strong> \u2014 attach hotspots to images inside Gutenberg galleries.","7":"<strong>ACF support<\/strong> \u2014 compatible with ACF image, gallery, and repeater fields.","8":"<strong>Page builder friendly<\/strong> \u2014 Divi, Beaver Builder, WPBakery and any other builder that renders WordPress shortcodes work out of the box.","9":"<strong>Shortcode<\/strong> \u2014 embed any hotspot image anywhere with <code>[wphs_image id=\"123\"]<\/code>.","10":"<strong>Gallery slider<\/strong> \u2014 group multiple hotspot images into a responsive carousel with <code>[wphs_gallery id=\"X\"]<\/code>.","11":"<strong>Custom hotspot icon<\/strong> \u2014 replace the default dot with any image from the Media Library.","12":"<strong>Accessible by default<\/strong> \u2014 keyboard navigation, screen-reader labels, focus indicators, <code>prefers-reduced-motion<\/code> support.","13":"<strong>Extensible<\/strong> \u2014 9 filters \/ actions for theme and plugin developers.","14":"<strong>Frontend rendering<\/strong> \u2014 physical CSS\/JS files, on-demand enqueue, no inline assets in the head.","15":"<code>size<\/code> \u2014 image size (default: <code>large<\/code>). Accepts any registered WordPress image size.","16":"<p><code>class<\/code> \u2014 additional CSS class added to the <code>&lt;img&gt;<\/code> tag.<\/p>\n\n<p>[wphs_gallery id=\"GALLERY_ID\" nav=\"dots+arrows\" cols_desktop=\"3\" cols_mobile=\"1\"]<\/p>","17":"WordPress 6.0 or later","18":"PHP 7.4 or later","19":"jQuery (included with WordPress)","20":"<code>wphs_default_settings<\/code> (filter) \u2014 modify the default plugin options.","21":"<code>wphs_hotspot_data<\/code> (filter) \u2014 modify the hotspot list before rendering.","22":"<code>wphs_tooltip_html<\/code> (filter) \u2014 modify the per-hotspot tooltip HTML.","23":"<code>wphs_allowed_iframe_attrs<\/code> (filter) \u2014 extend the iframe allowlist used by <code>wp_kses<\/code>.","24":"<code>wphs_allowed_iframe_hosts<\/code> (filter) \u2014 extend the host allowlist for iframe <code>src<\/code> attributes.","25":"<code>wphs_oembed_providers<\/code> (filter) \u2014 enable\/disable server-side oEmbed providers.","26":"<code>wphs_hotspot_aria_label<\/code> (filter) \u2014 override the default screen-reader label.","27":"<code>wphs_before_render_image<\/code> (action) \u2014 fire just before <code>[wphs_image]<\/code> outputs HTML.","28":"<code>wphs_after_save_hotspots<\/code> (action) \u2014 fire after hotspots are persisted.","29":"<code>wphs_loaded<\/code> (action) \u2014 fire after the plugin has booted all subsystems."}},"plugin_section":[],"plugin_tags":[76538,146663,3538,127148,788],"plugin_category":[],"plugin_contributors":[262870],"plugin_business_model":[],"class_list":["post-312121","plugin","type-plugin","status-publish","hentry","plugin_tags-elementor","plugin_tags-image-hotspot","plugin_tags-image-map","plugin_tags-interactive-image","plugin_tags-tooltip","plugin_contributors-bypleaseup","plugin_committers-bypleaseup"],"banners":{"banner":"https:\/\/ps.w.org\/pleaseup-hotspots\/assets\/banner-772x250.png?rev=3532106","banner_2x":"https:\/\/ps.w.org\/pleaseup-hotspots\/assets\/banner-1544x500.png?rev=3532106","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/pleaseup-hotspots\/assets\/icon-128x128.png?rev=3532106","icon_2x":"https:\/\/ps.w.org\/pleaseup-hotspots\/assets\/icon-256x256.png?rev=3532106","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/pleaseup-hotspots\/assets\/screenshot-1.png?rev=3532145","caption":"Plugin admin overview \u2014 image hotspot collections listed in the WordPress back-office."}],"raw_content":"<!--section=description-->\n<p><strong>Image Hotspots by Pleaseup<\/strong> is a responsive <strong>image hotspot<\/strong> plugin that lets you add <strong>interactive image maps<\/strong>, <strong>tooltips<\/strong>, and <strong>annotations<\/strong> to any image with a visual drag &amp; drop editor. Fully compatible with <strong>Elementor<\/strong> (free and Pro), the <strong>Gutenberg<\/strong> block editor, and <strong>ACF<\/strong> \u2014 no add-on required.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin contacts third-party services in two distinct flows. Both flows are triggered only by an authenticated editor (with <code>edit_posts<\/code>) pasting a URL inside a tooltip; no data leaves the site automatically.<\/p>\n\n<p><strong>Server-side oEmbed resolution<\/strong> (<code>wp_oembed_get<\/code>)<\/p>\n\n<p>When the editor pastes a URL from one of the supported oEmbed providers into a tooltip, the plugin calls the provider's oEmbed endpoint server-side via WordPress core's <code>wp_oembed_get()<\/code> to retrieve the embed HTML. The URL pasted by the editor is sent to the provider; no other data is sent. Supported providers:<\/p>\n\n<ul>\n<li>YouTube \u2014 Terms: https:\/\/www.youtube.com\/t\/terms \u2014 Privacy: https:\/\/policies.google.com\/privacy<\/li>\n<li>Vimeo \u2014 Terms: https:\/\/vimeo.com\/terms \u2014 Privacy: https:\/\/vimeo.com\/privacy<\/li>\n<li>Spotify \u2014 Terms: https:\/\/www.spotify.com\/legal\/end-user-agreement\/ \u2014 Privacy: https:\/\/www.spotify.com\/legal\/privacy-policy\/<\/li>\n<\/ul>\n\n<p><strong>Client-side iframe rendering<\/strong><\/p>\n\n<p>When a tooltip containing an oEmbed iframe is opened on a public page, the visitor's browser loads the iframe directly from the provider's CDN (e.g. <code>youtube.com<\/code>, <code>player.vimeo.com<\/code>, <code>open.spotify.com<\/code>). This is standard browser behavior for any embedded media; the plugin does not add any tracking on top.<\/p>\n\n<p>The set of allowed iframe hosts is filterable via the <code>wphs_allowed_iframe_hosts<\/code> filter. Hosts not in the allowlist are stripped from tooltip HTML on save.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Upload the <code>pleaseup-hotspots<\/code> folder to the <code>\/wp-content\/plugins\/<\/code> directory, or install the plugin directly from the WordPress plugin repository.<\/li>\n<li>Activate the plugin through the <strong>Plugins<\/strong> menu in WordPress.<\/li>\n<li>Navigate to <strong>Image Hotspots \u2192 Editor<\/strong> in the admin sidebar.<\/li>\n<li>Select an image from the Media Library and start adding hotspots.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"how%20do%20i%20add%20a%20hotspot%20to%20an%20image%3F\"><h3>How do I add a hotspot to an image?<\/h3><\/dt>\n<dd><p>Go to <strong>Image Hotspots \u2192 Editor<\/strong>, select an image from the Media Library, then click anywhere on the image preview to create a hotspot. Drag it to reposition it, then click the hotspot to edit the HTML content of the popup layer.<\/p><\/dd>\n<dt id=\"how%20do%20i%20display%20the%20image%20with%20hotspots%20on%20the%20front%20end%3F\"><h3>How do I display the image with hotspots on the front end?<\/h3><\/dt>\n<dd><p>Use the shortcode <code>[wphs_image id=\"123\"]<\/code> where <code>123<\/code> is the attachment ID of the image. You can also use the shortcode in any post, page, or widget area that supports shortcodes.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20gutenberg%20image%20blocks%3F\"><h3>Does it work with Gutenberg image blocks?<\/h3><\/dt>\n<dd><p>Yes. Hotspots are stored against the attachment ID, so any block that references that attachment (image block, gallery block, ACF image fields) inherits the configured hotspots when rendered through the <code>[wphs_image]<\/code> shortcode.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20page%20builders%20%28elementor%2C%20divi%2C%20beaver%20builder%29%3F\"><h3>Does it work with page builders (Elementor, Divi, Beaver Builder)?<\/h3><\/dt>\n<dd><p>Yes via the <code>[wphs_image]<\/code> and <code>[wphs_gallery]<\/code> shortcodes. CSS and JS are enqueued defensively for builders that render shortcodes after <code>wp_head<\/code>.<\/p><\/dd>\n<dt id=\"are%20hotspot%20positions%20responsive%3F\"><h3>Are hotspot positions responsive?<\/h3><\/dt>\n<dd><p>Yes. Coordinates are stored as percentages of the natural image dimensions, so they scale with any rendered image size.<\/p><\/dd>\n<dt id=\"can%20i%20use%20a%20custom%20icon%20instead%20of%20the%20default%20dot%3F\"><h3>Can I use a custom icon instead of the default dot?<\/h3><\/dt>\n<dd><p>Yes. In the per-image settings, switch the hotspot style to <em>Image<\/em>, upload or choose your custom icon from the Media Library, and save.<\/p><\/dd>\n<dt id=\"does%20it%20work%20with%20acf%3F\"><h3>Does it work with ACF?<\/h3><\/dt>\n<dd><p>Yes. The plugin stores hotspot data as post meta on the attachment, so any image displayed via <code>wp_get_attachment_image()<\/code> \u2014 including ACF image, gallery, and repeater fields \u2014 can use the shortcode to render with hotspots.<\/p><\/dd>\n<dt id=\"will%20uninstalling%20the%20plugin%20delete%20my%20data%3F\"><h3>Will uninstalling the plugin delete my data?<\/h3><\/dt>\n<dd><p>Yes. When you uninstall the plugin (not just deactivate it), all hotspot settings, attachment meta, and the plugin's custom post type contents (galleries and tooltips) are removed from the database.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>3.1.4<\/h4>\n\n<ul>\n<li>Hotfix: frontend <code>[wphs_image]<\/code> now renders oEmbed iframes (Vimeo, YouTube, Spotify, SoundCloud) correctly again. In 3.1.3 the shared <code>Sanitizer::kses_tooltip_html()<\/code> helper \u2014 newly used by the frontend \u2014 ran a final <code>preg_replace<\/code> pass that stripped <strong>every<\/strong> <code>&lt;\/iframe&gt;<\/code> from the tooltip HTML, including the ones legitimately closing preserved iframes. The browser parser, seeing an unclosed <code>&lt;iframe&gt;<\/code>, then swallowed the rest of the page as iframe fallback content, leaving only the image visible. The extra pass has been removed; iframes with an allowed host survive both the opening tag and the closing tag intact. No data migration required \u2014 the stored tooltip HTML is untouched, only the render path is fixed.<\/li>\n<\/ul>\n\n<h4>3.1.3<\/h4>\n\n<ul>\n<li>Compatibility: declared \"Tested up to\" WordPress 7.1. Full security + compatibility audit against the WP 7.1.2 core surface \u2014 no deprecated APIs used, no runtime warnings, all AJAX endpoints continue to satisfy the nonce -&gt; capability -&gt; sanitize contract.<\/li>\n<li>Security hardening: the frontend <code>[wphs_image]<\/code> renderer now sanitizes tooltip HTML through the shared <code>Sanitizer::kses_tooltip_html()<\/code> helper. Third-party integrations that hook into the <code>wphs_tooltip_html<\/code> filter now inherit the same host-allowlist iframe stripping that the server-side save path already applied, closing a defense-in-depth gap.<\/li>\n<li>Housekeeping: removed the unused <code>jquery-ui-draggable<\/code> script enqueue on the plugin's admin screens. The drag-and-drop editor uses native pointer events, not jQuery UI, so this dependency was dead code \u2014 dropping it insulates the plugin from the jQuery UI 1.14.2 API removals shipped in WordPress 7.1.<\/li>\n<\/ul>\n\n<h4>3.1.2<\/h4>\n\n<ul>\n<li>Release pipeline hotfix: forces a clean re-deploy. The 3.1.1 tag landed on WordPress.org SVN with the pre-bump code due to a release-event race condition that fired before the version-coherence sanity check. Plugin payload is identical to the intended 3.1.1.<\/li>\n<\/ul>\n\n<h4>3.1.1<\/h4>\n\n<ul>\n<li>Compatibility: declared \"Tested up to\" WordPress 7.0. No code changes \u2014 the plugin uses only long-stable WordPress Core APIs and was verified compatible with the 7.0 release.<\/li>\n<\/ul>\n\n<h4>3.1.0<\/h4>\n\n<ul>\n<li>Rebranded plugin display name to \"Image Hotspots by Pleaseup\" for better discoverability on WordPress.org search.<\/li>\n<li>Updated readme tags and short description for clarity.<\/li>\n<li>Admin menu label updated to \"Image Hotspots\" (page title remains in the same location).<\/li>\n<li>No functional or breaking changes \u2014 existing shortcodes, settings, hooks, post types, and stored data remain fully compatible.<\/li>\n<\/ul>\n\n<h4>3.0.3<\/h4>\n\n<ul>\n<li>Build: excluded <code>.gitkeep<\/code> placeholder files from the distribution zip (WordPress.org plugin scanner flags any hidden file).<\/li>\n<li>readme.txt: bumped \"Tested up to\" to 6.9.<\/li>\n<\/ul>\n\n<h4>3.0.2<\/h4>\n\n<ul>\n<li>Admin: renamed the admin sidebar menu label and the in-page hero <code>&lt;h1&gt;<\/code> from \"WP Hotspots\" \/ \"WP Image HotSpots\" to \"Pleaseup Hotspots\" to match the plugin name.<\/li>\n<li>readme.txt: updated installation and FAQ instructions to refer to the new menu label.<\/li>\n<li>Translations: POT regenerated for the renamed strings.<\/li>\n<\/ul>\n\n<h4>3.0.1<\/h4>\n\n<ul>\n<li>Renamed plugin to \"Pleaseup Hotspots\" (slug <code>pleaseup-hotspots<\/code>) for the WordPress.org Plugin Directory.<\/li>\n<li>Frontend: extracted the gallery carousel JavaScript and dynamic CSS to enqueued assets (no more inline <code>&lt;script&gt;<\/code> or <code>&lt;style&gt;<\/code> blocks in the rendered shortcode HTML). The dynamic per-instance values are now passed as CSS custom properties on the wrapper.<\/li>\n<li>Admin: the gallery preview now reuses the same enqueued frontend assets so the in-editor preview matches the public render exactly.<\/li>\n<\/ul>\n\n<h4>3.0.0<\/h4>\n\n<p>Initial release.<\/p>","raw_excerpt":"Interactive image hotspots with drag &amp; drop editor. Compatible with Elementor, Gutenberg, and ACF. Add tooltips, annotations, and image maps.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/312121","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=312121"}],"author":[{"embeddable":true,"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/bypleaseup"}],"wp:attachment":[{"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=312121"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=312121"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=312121"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=312121"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=312121"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/brx.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=312121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}