{"id":917,"date":"2024-05-07T11:45:36","date_gmt":"2024-05-07T11:45:36","guid":{"rendered":"https:\/\/kb.shortpixel.com\/docs\/actions-and-filters-of-shortpixel-adaptive-images\/"},"modified":"2025-08-27T08:40:23","modified_gmt":"2025-08-27T08:40:23","password":"","slug":"actions-and-filters-of-shortpixel-adaptive-images","status":"publish","type":"docs","link":"https:\/\/kb.shortpixel.com\/knowledge-base\/article\/actions-and-filters-of-shortpixel-adaptive-images\/","title":{"rendered":"Actions, filters and developer options of ShortPixel Adaptive Images"},"content":{"rendered":"\n<p><a href=\"https:\/\/wordpress.org\/plugins\/shortpixel-adaptive-images\/\" target=\"_blank\" rel=\"noopener\">ShortPixel Adaptive Images<\/a> calls the following actions and filters. Here you can also find other configurations that you can add to your website as a developer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Custom replacement rules<\/h2>\n\n\n\n<p>As you know, every time one of your website&#8217;s pages is visited, <a href=\"https:\/\/wordpress.org\/plugins\/shortpixel-adaptive-images\/\" rel=\"noopener\">ShortPixel Adaptives Images<\/a> (SPAI)\u00a0analyzes the code and replaces the URL of each original, non-optimized image with the URL of the right-sized optimized image. Each replaced image is served from the <a href=\"https:\/\/shortpixel.com\/knowledge-base\/article\/what-is-the-cdn-good-for\/\" rel=\"noopener\">ShortPixel CDN<\/a>.<\/p>\n\n\n\n<p>The plugin looks in the most typical places where image URLs are located, such as in the\u00a0<code class=\"inline-code\">src<\/code> attribute of\u00a0<code class=\"inline-code\">img<\/code> tags. However,\u00a0if your URLs aren&#8217;t recognized correctly by our plugin, you can add your own replacement rule.<\/p>\n\n\n\n<p>First, add this filter to the functions.php file of your theme:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_filter('shortpixel\/ai\/customRules', 'my_custom_spai');<\/code><\/pre>\n\n\n\n<p>The <code class=\"inline-code\">my_custom_spai<\/code> function is given an array and should append elements of type <code class=\"inline-code\">ShortPixelAITagRule<\/code> to it: <code class=\"inline-code\">[ 'tagName', 'attrToBeChecked', 'classFilter', 'attributeFilter', false (reserved), 'attributeValueFilter', isEager (bool), 'type', callback (bool), quickMatch (bool), frontEager (bool) ]<\/code>\u00a0<\/p>\n\n\n\n<p>The elements of the array are, in this order:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code class=\"inline-code\">tagName<\/code> \u2013 The name of the HTML tag.<\/li>\n\n\n\n<li><code class=\"inline-code\">attrToBeChecked<\/code> \u2013 The attribute to be replaced.<\/li>\n\n\n\n<li><code class=\"inline-code\">classFilter<\/code> \u2013 A class filter. If it&#8217;s set, only elements with this class will be replaced. The default is <code class=\"inline-code\">false<\/code> .<\/li>\n\n\n\n<li><code class=\"inline-code\">attributeFilter<\/code> \u2013 An attribute filter. If it&#8217;s set, only elements with this attribute will be replaced. The default is <code class=\"inline-code\">false<\/code> .<\/li>\n\n\n\n<li><code class=\"inline-code\">false<\/code> &#8211; Reserved.<\/li>\n\n\n\n<li><code class=\"inline-code\">attributeValueFilter<\/code> \u2013\u00a0An attribute value filter.\u00a0If it&#8217;s set, only elements with this attribute value will be replaced. The default is <code class=\"inline-code\">false<\/code> .<\/li>\n\n\n\n<li><code class=\"inline-code\">mergeAttr<\/code> \u2013 Advanced usage (see plugin code). The default is <code class=\"inline-code\">false<\/code> .<\/li>\n\n\n\n<li><code class=\"inline-code\">isEager<\/code> \u2013 If <code class=\"inline-code\">true<\/code> , the image will be replaced server-side and not lazy-loaded. Otherwise the image will be lazy-loaded.<\/li>\n\n\n\n<li><code class=\"inline-code\">type<\/code> \u2013 Advanced usage (see plugin code). The default is <code class=\"inline-code\">'url'<\/code> . It can also be <code class=\"inline-code\">'srcset'<\/code> if the image has a <code class=\"inline-code\">srcset<\/code> structure.<\/li>\n\n\n\n<li><code class=\"inline-code\">callback<\/code> \u2013 Advanced usage (see plugin code). The default is <code class=\"inline-code\">false<\/code> .\u00a0Must be\u00a0<code class=\"inline-code\">'replace_custom_srcset'<\/code> if the type is <code class=\"inline-code\">srcset<\/code> .<\/li>\n\n\n\n<li><code class=\"inline-code\">quickMatch<\/code> \u2013 Advanced usage (see plugin code). The default is <code class=\"inline-code\">false<\/code> .<\/li>\n\n\n\n<li><code class=\"inline-code\">frontEager<\/code> \u2013 Advanced usage (see plugin code). The default is <code class=\"inline-code\">false<\/code> .<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Example 1<\/h3>\n\n\n\n<p>Here&#8217;s a real-world example of custom image attributes, a custom <code class=\"inline-code\">srcset<\/code> and a custom JSON data attribute:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_filter('shortpixel\/ai\/customRules', 'spai_to_iconic');\n\nfunction spai_to_iconic($regexItems) {\n    \/\/lazy-loaded data-iconic-woothumbs-src attribute\n    $regexItems&#91;] = new ShortPixelAITagRule('img', 'data-iconic-woothumbs-src');\n    \/\/eager attribute\n    $regexItems&#91;] = new ShortPixelAITagRule('img', 'data-large_image', false, false, false, false, true);\n    \/\/lazy srcset style attribute.\n    $regexItems&#91;] = new ShortPixelAITagRule('img', 'srcset', false, false, false, false, false, 'srcset', 'replace_custom_srcset');\n    $regexItems&#91;] = new ShortPixelAITagRule('div', 'data-default', 'iconic-woothumbs-all-images-wrap', false, false, false, false, 'srcset', 'replace_custom_json_attr');\n    return $regexItems;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Example 2<\/h3>\n\n\n\n<p>Imagine you have this <code class=\"inline-code\">section<\/code> tag on your website:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;section id=\"hero\" data-images=\"&#91;\"https:\/\/deltidsbrandman.se\/wp-content\/uploads\/2022\/12\/brandman-2.jpg\"]\" class=\"hero-slideshow-wrapper hero-slideshow-normal\">&lt;\/section><\/code><\/pre>\n\n\n\n<p>As you can see, this example is a bit more complicated because the image is contained in an array. In this case, we&#8217;d insert the snippet as follows:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_filter('shortpixel\/ai\/customRules', 'spai_handle_section_data_images');\n\nfunction spai_handle_section_data_images($regexItems) {\n    $regexItems&#91;] = new ShortPixelAITagRule('section', 'data-images', 'hero-slideshow-wrapper', false, false, false, true, 'srcset', 'replace_custom_json_attr');\n    return $regexItems;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Example 3<\/h3>\n\n\n\n<p>Suppose we have images in tags like this one:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;a href=\".....\" data-rl_title&gt;<\/code><\/pre>\n\n\n\n<p>In this case, the snippet to add is:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_filter('shortpixel\/ai\/customRules', 'spai_lightbox');\n\nfunction spai_lightbox($regexItems) {\n    $regexItems&#91;] = new ShortPixelAITagRule('a', 'href', false, 'data-rl_title', false, false, true);\n    return $regexItems;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Custom replacement rules (frontend only)<\/h2>\n\n\n\n<p>If you need a rule to be applied to the frontend only, you can use the following filter in the same way as for the filter above:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_filter('shortpixel\/ai\/customFrontendRules', 'my_function');<\/code><\/pre>\n\n\n\n<p>This rule is applied only if the &#8220;New AI engine&#8221; option is enabled in SPAI&#8217;s settings. It is useful when you have content that is rendered by JavaScript and you need to do the replacement after the content is rendered. This is because the <code class=\"inline-code\">customFrontendRules<\/code> are only executed by the vanilla JS in the browser; they do not modify the HTML code that is sent to them, as the other rules do. This way, they are able to respond to content that is rendered dynamically, or content that is not easily identifiable by the PHP part of the plugin that does not render the page, such as a link that does not have a class or a specific attribute.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Example<\/h3>\n\n\n\n<p>Suppose we have images from an HTML link (<code class=\"inline-code\">&lt;div class=\"et_pb_gallery_image\">&lt;a href=\"#\">Example&lt;\/a>&lt;\/div><\/code>) and it has no attribute other than <code class=\"inline-code\">href<\/code>. The snippet would look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_filter('shortpixel\/ai\/customFrontendRules', 'spai_the_gallery_ahrefs');\n\nfunction spai_the_gallery_ahrefs($regexItems) {\n    $item = new ShortPixelAITagRule('div.et_pb_gallery_image a', 'href');\n    $item->frontEager = true;\n    $item->frontResize = false;\n    $regexItems&#91;] = $item;\n    return $regexItems;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Filenames with size suffix<\/h2>\n\n\n\n<p>If you have <strong>main<\/strong> images (not thumbnails) in the Media Library whose filename ends with the usual thumbnail size suffix\u00a0(e.g. <code class=\"inline-code\">-100\u00d7100<\/code>), please add this in the wp-config.php file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>define('SPAI_FILENAME_RESOLUTION_UNSAFE', true);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">JavaScript post-processing<\/h2>\n\n\n\n<p>If you want to do post-processing in JavaScript after the image\/tag has been updated by ShortPixel AI, you can add a callback like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>jQuery( document ).ready(function() {\n    ShortPixelAI.registerCallback('element-updated', function(elm){\n        \/\/ elm is the jQuery object, elm&#91;0] is the tag\n        console.log(\"element updated: \" + elm.prop('nodeName'));\n    });\n});<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Change original URL<\/h2>\n\n\n\n<p>To change the original URL of the image detected by ShortPixel, use this filter that receives the original URL:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>add_filter('shortpixel\/ai\/originalUrl', 'my_function');<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Force cropping<\/h2>\n\n\n\n<p>Sometimes, when the Smart crop option is enabled, ShortPixel AI thinks it is not safe to crop an image, but you want to crop it anyway. Please add this attribute to force cropping:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;img data-spai-crop=\"true\" ....<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>ShortPixel Adaptive Images calls the following actions and filters. Here you can also find other configurations that you can add to your website as a developer. Custom replacement rules As you know, every time one of your website&#8217;s pages is visited, ShortPixel Adaptives Images (SPAI)\u00a0analyzes the code and replaces the URL of each original, non-optimized [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","template":"","meta":{"footnotes":""},"doc_category":[35],"glossaries":[],"doc_tag":[],"class_list":["post-917","docs","type-docs","status-publish","hentry","doc_category-shortpixel-adaptive-images"],"blocksy_meta":[],"year_month":"2026-04","word_count":957,"total_views":"1099","reactions":{"happy":"0","normal":"0","sad":"0"},"author_info":{"name":"admin","author_nicename":"admin_mdli53m5","author_url":"https:\/\/kb.shortpixel.com\/author\/admin_mdli53m5\/"},"doc_category_info":[{"term_name":"ShortPixel Adaptive Images","term_url":"https:\/\/kb.shortpixel.com\/knowledge-base\/category\/shortpixel-adaptive-images\/"}],"doc_tag_info":[],"knowledge_base_info":[],"knowledge_base_slug":[],"_links":{"self":[{"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/docs\/917","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/docs"}],"about":[{"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/types\/docs"}],"author":[{"embeddable":true,"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/comments?post=917"}],"version-history":[{"count":2,"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/docs\/917\/revisions"}],"predecessor-version":[{"id":2106,"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/docs\/917\/revisions\/2106"}],"wp:attachment":[{"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/media?parent=917"}],"wp:term":[{"taxonomy":"doc_category","embeddable":true,"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/doc_category?post=917"},{"taxonomy":"glossaries","embeddable":true,"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/glossaries?post=917"},{"taxonomy":"doc_tag","embeddable":true,"href":"https:\/\/kb.shortpixel.com\/wp-json\/wp\/v2\/doc_tag?post=917"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}