{"id":21628,"date":"2017-11-08T17:43:16","date_gmt":"2017-11-08T17:43:16","guid":{"rendered":"http:\/\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1"},"modified":"2024-06-01T10:50:43","modified_gmt":"2024-06-01T17:50:43","slug":"dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1","title":{"rendered":"Dynamic Image Manipulation and Optimization is eZ-er with the Novactive eZ Platform Cloudinary Connector"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p><em>(Guest post by <a href=\"https:\/\/www.linkedin.com\/in\/sebastienmorel\/\">Sebastien Morel<\/a>)<\/em>\n<br><\/p>\n<h2>Introduction<\/h2>\n<p>At Novactive, we are always excited to use new technologies and\/or to improve our favorite technologies with other ones when it makes sense for us, for our clients and for the community.<\/p>\n<p>Our business is web technologies, and the most professional content management system (CMS) for us is eZ Platform (previously eZ Publish). That\u2019s why we love creating connectors to this CMS. Our most recent eZ project is an image management plugin using Cloudinary.<\/p>\n<p>If you are a web developer, whether or not you already use eZ Platform, Symfony, or Cloudinary, your website probably has some images, so take a look at what this cool connection can offer.<\/p>\n<h2>eZ Platform Quick Notes<\/h2>\n<p>If you aren\u2019t familiar with this CMS, you should have a look, but before we dive into the details about our Cloudinary integration, I just want to share in a few words the main reasons why I think <a href=\"https:\/\/ezplatform.com\/\">eZ Platform<\/a> is the best PHP CMS:<\/p>\n<ul>\n<li>\n<strong>Fully based on the Symfony PHP framework<\/strong>: eZ Platform is a Symfony application, as opposed to just using some Symfony components as others do. If you are a Symfony developer, you\u2019ll feel right at home.<\/li>\n<li>\n<strong>Decoupled CMS<\/strong>: eZ Platform separates the content creation process from the delivery process.<\/li>\n<li>\n<strong>Headless CMS<\/strong>: Thanks to the REST API, the presentation does not have to be handled by the CMS (but it can be)<\/li>\n<li>\n<strong>Mature<\/strong>: It\u2019s been around for more than 10 years.<\/li>\n<li>\n<strong>Supported<\/strong>: by <a href=\"https:\/\/ez.no\">eZ Systems<\/a>\n<\/li>\n<\/ul>\n<h2>A Bit about Cloudinary<\/h2>\n<p><a href=\"https:\/\/cloudinary.com\/\">Cloudinary<\/a> is a cloud-based, end-to-end media management solution that automates and streamlines your entire media asset workflow. It <strong>removes all the hassles<\/strong> you would normally need to handle for your site\u2019s <strong>images and videos<\/strong>, including <strong>responsiveness, compression, transformation, hosting, caching, delivery<\/strong> and more!<\/p>\n<p>The benefits of Cloudinary go way beyond this plugin and we can\u2019t possibly cover them all here. In this post, we are going to focus specifically on the eZ plugin offering, where our main goal was to let eZ Platform developers enjoy Cloudinary\u2019s powerful <strong>image optimization capabilities<\/strong> and provide easy access to all of Cloudinary\u2019s transformation features, including:<\/p>\n<ul>\n<li>Advanced resizing<\/li>\n<li>Smart detection-based cropping<\/li>\n<li>Face detection<\/li>\n<li>Instagram-like effects<\/li>\n<li>Sprite and CSS generation<\/li>\n<li>Transformation chaining<\/li>\n<\/ul>\n<p>For example, check out just some of what you can do just by specifying a few resizing and face-detection parameters:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/eZ_Novactive_transformations.png\" alt=\"Cloudinary transformation examples resize and face detection\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1220\" height=\"972\"\/><\/p>\n<p>For more examples of the available transformations, take a look at Cloudinary\u2019s <a href=\"https:\/\/cloudinary.com\/products\/programmable_media\">image manipulation<\/a>, or the full list of all available options in the <a href=\"https:\/\/cloudinary.com\/documentation\/transformation_reference\">Cloudinary transformation reference.<\/a><\/p>\n<p>By taking advantage of the Cloudinary plugin, you <strong>decouple<\/strong> your <strong>application<\/strong> a bit more, you get <strong>amazing transformation features<\/strong> instantly, and automatic optimizations that will give a significant boost to your page load <strong>performance<\/strong>!<\/p>\n<h2>Motivation<\/h2>\n<p>\u201cContent is king\u201d in a web or a mobile project. You always need images or videos with your content.<\/p>\n<p>Then you need to optimize them, store them in different adapted versions (known as variations), host them all, cache them and deliver them.<\/p>\n<p>But you don\u2019t want to reinvent the wheel. Plus image management is not likely your domain of expertise, so it\u2019s probably not the area where want to invest your time and resources. That\u2019s why we decided to create a plugin that can add Cloudinary on top of <strong>an existing eZ website<\/strong> smoothly, <strong>with almost no development required<\/strong>.<\/p>\n<p>Our requirements for this <strong>M<\/strong>inimum <strong>V<\/strong>iable <strong>P<\/strong>lugin were:<\/p>\n<ul>\n<li>Using Cloudinary with <strong>no change on the architecture<\/strong>\n<\/li>\n<li>\n<strong>No changes in the source code<\/strong>\n<\/li>\n<li>\n<strong>Original images stay<\/strong> on the <strong>eZ Platform local environment<\/strong> (in case you want to stop using Cloudinary in the future)<\/li>\n<li>The plugin should <strong>work on existing projects<\/strong> and <strong>provide<\/strong> Cloudinary\u2019s <strong>transformations<\/strong> and <strong>delivery features<\/strong>\n<\/li>\n<\/ul>\n<p>So the requirements are simple in this <strong>MVP<\/strong>, and you still get to <strong>host the original image locally<\/strong>.<\/p>\n<h2>eZ Platform Default Image Handling<\/h2>\n<p>By default, eZ provides a concept of \u201cvariation\u201d (previously known as \u201caliases\u201d). This is a cool feature that many CMS still lack. It enables developers to make sure images are rendered in an optimized way in the various places they need to appear, for example: on a homepage at a certain size and on a detailed article page at a different size. This already helps prevents editors from loading super-heavy images directly into pages. But it\u2019s far from optimum and, as we will see, Cloudinary can do much better.<\/p>\n<p>By default, these image variations are generated with <a href=\"https:\/\/github.com\/liip\/LiipImagineBundle\">LiipImagineBundle<\/a>, using the underlying <a href=\"https:\/\/github.com\/avalanche123\/Imagine\">Imagine<\/a>. It supports GD, Imagick or Gmagick PHP extensions, and allows you to define a flexible filter to convert your original images into multiple \u201cvariations.\u201d<\/p>\n<p>eZ also abstracts the file system. By default, variations are stored on the file system, but you can configure it to store those images in an AWS S3 bucket if you wish. Obviously, they are generated only once and cleared on demand (e.g. content removal).<\/p>\n<p>Here is an example of a variation definition:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">            <span class=\"hljs-selector-tag\">simple<\/span>:\n                <span class=\"hljs-selector-tag\">reference<\/span>: ~\n                <span class=\"hljs-selector-tag\">filters<\/span>:\n                    <span class=\"hljs-selector-tag\">-<\/span> { <span class=\"hljs-attribute\">name<\/span>: auto_rotate }\n                    <span class=\"hljs-selector-tag\">-<\/span> { <span class=\"hljs-attribute\">name<\/span>: geometry\/scaledownonly, params: &#91;<span class=\"hljs-number\">128<\/span>,<span class=\"hljs-number\">128<\/span>] }\n                    <span class=\"hljs-selector-tag\">-<\/span> { <span class=\"hljs-attribute\">name<\/span>: strip }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>A more complex one:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">           <span class=\"hljs-selector-tag\">complex<\/span>:\n                <span class=\"hljs-selector-tag\">reference<\/span>: ~\n                <span class=\"hljs-selector-tag\">filters<\/span>:\n                    <span class=\"hljs-selector-tag\">-<\/span> { <span class=\"hljs-attribute\">name<\/span>: auto_rotate }\n                    <span class=\"hljs-selector-tag\">-<\/span> { <span class=\"hljs-attribute\">name<\/span>: geometry\/scaledownonly, params: &#91;<span class=\"hljs-number\">326<\/span>,<span class=\"hljs-number\">280<\/span>] }\n                    <span class=\"hljs-selector-tag\">-<\/span> { <span class=\"hljs-attribute\">name<\/span>: geometry\/crop, params: &#91;<span class=\"hljs-number\">326<\/span>, <span class=\"hljs-number\">280<\/span>, <span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>] }\n                    <span class=\"hljs-selector-tag\">-<\/span> { <span class=\"hljs-attribute\">name<\/span>: background, params: { size: &#91;<span class=\"hljs-number\">230<\/span>, <span class=\"hljs-number\">144<\/span>], color: <span class=\"hljs-string\">'#FFFFFF'<\/span> } }\n                    <span class=\"hljs-selector-tag\">-<\/span> { <span class=\"hljs-attribute\">name<\/span>: strip }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This is a great start, but it\u2019s not enough, as your servers still need to manage the conversion, storage, delivery and caching.\nYou are also limited to the PHP extension capabilities and the delivery capabilities of your servers\/tools. And of-course you are lacking all the sophisticated transformation features that a service like Cloudinary can provide.<\/p>\n<h2>Benefits of the MVP<\/h2>\n<p>The plugin will give you the ability to create variations based on Cloudinary features.\nIn other words, <strong>every transformation feature available in Cloudinary will be yours as soon as you finish the plugin installation<\/strong>.<\/p>\n<p>There is no code to change, just the variations to define, and if you don\u2019t define them, the plugin will fallback to the standard handling.<\/p>\n<p>Example of a Cloudinary variation:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">            <span class=\"hljs-keyword\">case<\/span>:\n                ezreference_variation: ~\n                filters:\n                    width: <span class=\"hljs-number\">710<\/span>\n                    <span class=\"hljs-attr\">width<\/span>: <span class=\"hljs-number\">428<\/span>\n                    <span class=\"hljs-attr\">crop<\/span>: <span class=\"hljs-string\">'fit'<\/span>\n                    <span class=\"hljs-attr\">fetch_format<\/span>: <span class=\"hljs-string\">'auto'<\/span>\n                    <span class=\"hljs-attr\">effect<\/span>: <span class=\"hljs-string\">\"brightness:200\"<\/span>\n                    <span class=\"hljs-attr\">radius<\/span>: <span class=\"hljs-string\">'max'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>And the \u201c<strong>filters<\/strong>\u201d key enables you to use the <a href=\"https:\/\/cloudinary.com\/documentation\/image_transformations\">hundreds of possibilities<\/a> and combinations provided by Cloudinary.<\/p>\n<p>Plus:<\/p>\n<ul>\n<li>Images are automatically served through Cloudinary\u2019s servers, and every image is optimized to deliver the best possible quality at the smallest possible file size based on the content of the image and the specific browser that each customer uses to view your content.<\/li>\n<li>No computation is done on your servers to convert images.<\/li>\n<\/ul>\n<h2>How to Install the Plugin<\/h2>\n<p>The package is open source and available on our Github here: <a href=\"https:\/\/github.com\/Novactive\/NovaeZCloudinaryBundle\">https:\/\/github.com\/Novactive\/NovaeZCloudinaryBundle.<\/a><\/p>\n<ol>\n<li>The installation is quite standard, using composer.<\/li>\n<\/ol>\n<pre class=\"js-syntax-highlighted\"><code>$ composer require novactive\/ezcloudinarybundle\n<\/code><\/pre>\n<ol start=\"2\">\n<li>Register the bundle in your Kernel.<\/li>\n<\/ol>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\"> <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">registerBundles<\/span><span class=\"hljs-params\">()<\/span>\n<\/span>{\n   ...\n   $bundles = <span class=\"hljs-keyword\">array<\/span>(\n       <span class=\"hljs-keyword\">new<\/span> FrameworkBundle(),\n       ...\n       <span class=\"hljs-keyword\">new<\/span> Novactive\\Bundle\\eZCloudinaryBundle\\NovaeZCloudinaryBundle(),\n   );\n   ...\n}\n\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<ol start=\"3\">\n<li>Set up your credentials.\nIf you have not already done so, create a <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">Cloudinary account<\/a>. You can find your account credentials in the Cloudinary management console.<\/li>\n<\/ol>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"> nova_ezcloudinary:\n    authentification:\n        cloud_name: <span class=\"hljs-string\">\"xxx\"<\/span>\n        <span class=\"hljs-attr\">api_key<\/span>: <span class=\"hljs-string\">\"xxxxx\"<\/span>\n        <span class=\"hljs-attr\">api_secret<\/span>: <span class=\"hljs-string\">\"xxxx\"<\/span>\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<ol start=\"4\">\n<li>Set up variation templates:<\/li>\n<\/ol>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\"> system:\n    <span class=\"hljs-keyword\">default<\/span>:\n        cloudinary_variations:\n            simpletest1:\n                ezreference_variation: <span class=\"hljs-string\">'Native eZ Variation Name, ~ means original'<\/span>\n                filters: \n                <span class=\"hljs-comment\"># See Cloudinary documentation for available transformations:<\/span>\n                    width: <span class=\"hljs-number\">200<\/span>\n                    height: <span class=\"hljs-number\">200<\/span>\n                    gravity: <span class=\"hljs-string\">'face'<\/span>\n                    radius: <span class=\"hljs-string\">'max'<\/span>\n                    effect: <span class=\"hljs-string\">'sepia'<\/span>\n\n\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<ol start=\"5\">\n<li>Usage<\/li>\n<\/ol>\n<p><strong>NOTHING!<\/strong> That is another part of the beauty of eZ Platform.\nYour current template code should look like this:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">     {{ ez_render_field( content, <span class=\"hljs-string\">\"image\"<\/span>,{\n        <span class=\"hljs-string\">\"parameters\"<\/span>: {<span class=\"hljs-string\">\"alias\"<\/span>: <span class=\"hljs-string\">'simpletest1'<\/span>},\n        <span class=\"hljs-string\">\"attr\"<\/span> : { <span class=\"hljs-string\">\"class\"<\/span> : <span class=\"hljs-string\">\"img-responsive\"<\/span> }\n    }\n    ) }}\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>At this point, the plugin automatically takes over and the function <code>nova_ezcloudinary_alias<\/code> will be used instead of <code>ez_image_alias<\/code>. The bundle falls back on the native variation system if the alias name does not exist in <code>cloudinary_variations<\/code>.<\/p>\n<p>So basically there is no change in your code, just a <code>yaml<\/code> configuration for your variations.<\/p>\n<h2>How Does it Work?<\/h2>\n<p>The MVP uses the Cloudinary <a href=\"https:\/\/cloudinary.com\/documentation\/fetch_remote_images\">fetch<\/a> feature:<\/p>\n<p>The <code>nova_ezcloudinary_alias<\/code> will change the source of the image (at rendering) and generate a URL such as:<\/p>\n<pre class=\"js-syntax-highlighted\"><code>https:\/\/res.cloudinary.com\/demo\/image\/fetch\/c_fill,f_auto,g_auto,h_250,w_376\/http:\/\/www.yourwebsite.com\/var\/site\/storage\/images\/7\/5\/8\/0\/857-1-fre-FR\/20140708_120625.jpg\n<\/code><\/pre>\n<p><strong>Note<\/strong>: Cloudinary also offers a personalized CNAME URL adapted to your own domain option (High tier plans).<\/p>\n<p>The first time the image is requested, Cloudinary automatically fetches the original image from your eZ storage, stores it in a relative path in your Cloudinary account, and then performs the requested transformation so that all the variations are then hosted by Cloudinary and served via CDN.<\/p>\n<h2>Dynamic Responsive Images<\/h2>\n<p>Once you have Cloudinary at your service, you can use its capabilities to more easily deliver responsive images. There are three ways to do this:<\/p>\n<ol>\n<li>\n<p><strong>Dynamic image transformation<\/strong> &#8211; Use Cloudinary to generate transformed versions of images. Then use the HTML srcset attribute, enabling the browser to choose which image versions to display based on the device hosting the browser.<\/p>\n<\/li>\n<li>\n<p><strong>Automating responsive images with JavaScript (client side)<\/strong> &#8211; Programmatically set the &lt;img&gt; src URL.<\/p>\n<\/li>\n<li>\n<p><strong>Automating responsive images with Client Hints (server side)<\/strong> &#8211; Deliver the optimal image based on the available width reported in the Client Hints request header. But this is not available on all browsers.<\/p>\n<\/li>\n<\/ol>\n<p>We usually go with the <code>src<\/code> and <code>srcset<\/code> attribute of the &lt;img&gt; HTML tag as it does not require Javascript.<\/p>\n<p>Simply speaking, <code>srcset<\/code> provides to the browser a set of URLs (variations) to use depending on the viewport size. The browser takes the information, combines them with the window width and screen density it already knows and does its job!<\/p>\n<p>To exploit this feature with eZ, you just have to override the <code>ezimage<\/code> template to make it even more dynamic, using the following two steps:<\/p>\n<ol>\n<li>Create variations for each size:\n<ul>\n<li>myvariationname<\/li>\n<li>myvariationname_1x<\/li>\n<li>myvariationname_2x<\/li>\n<li>myvariationname_3x<\/li>\n<\/ul>\n<\/li>\n<li>Change the template that renders images, and adapt.<\/li>\n<\/ol>\n<p>Here\u2019s the code:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">{% block ezimage_field %}\n    {% spaceless %}\n        {% <span class=\"hljs-keyword\">if<\/span> not ez_is_field_empty( content, field ) %}\n            {% <span class=\"hljs-keyword\">set<\/span> aliasName = parameters.alias|default( 'original' ) %}\n            {% <span class=\"hljs-keyword\">set<\/span> imageAlias = nova_ezcloudinary_alias( field, versionInfo, aliasName ) %}\n            {% <span class=\"hljs-keyword\">set<\/span> src = imageAlias ? asset( imageAlias.uri ) : \"\/\/:0\" %}\n            {% <span class=\"hljs-keyword\">set<\/span> width = parameters.width is defined ? parameters.width : imageAlias.width %}\n            {% <span class=\"hljs-keyword\">set<\/span> height = parameters.height is defined ? parameters.height : imageAlias.height %}\n\n            {% <span class=\"hljs-keyword\">if<\/span> aliasName == <span class=\"hljs-string\">'original'<\/span> %}\n                {% <span class=\"hljs-keyword\">set<\/span> densities = &#91;] %}\n                {% <span class=\"hljs-keyword\">set<\/span> densitiesSizes = &#91;] %}\n            {% <span class=\"hljs-keyword\">else<\/span> %}\n                {% <span class=\"hljs-keyword\">set<\/span> densities = &#91;'1x', '2x', '3x'] %}\n                {% <span class=\"hljs-keyword\">set<\/span> densitiesSizes = &#91;'640w', '1040w', '1560w'] %}\n            {% endif %}\n\n            &lt;img {{ block( <span class=\"hljs-string\">'field_attributes'<\/span> ) }}\n                    src=<span class=\"hljs-string\">\"{{ src }}\"<\/span>{% <span class=\"hljs-keyword\">if<\/span> width %}\n                    width=<span class=\"hljs-string\">\"{{ width }}\"<\/span>{% endif %}{% <span class=\"hljs-keyword\">if<\/span> height %}\n                    height=<span class=\"hljs-string\">\"{{ height }}\"<\/span>{% endif %}\n                    alt=<span class=\"hljs-string\">\"{{ field.value.alternativeText }}\"<\/span>{% <span class=\"hljs-keyword\">if<\/span> parameters.class is defined and parameters.class is not empty %}\n                    <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span><\/span>=<span class=\"hljs-string\">\"{{ parameters.class }}\"<\/span>{% endif %}\n                    {% <span class=\"hljs-keyword\">if<\/span> densities|length &gt; <span class=\"hljs-number\">0<\/span> %}\n                        srcset=<span class=\"hljs-string\">\"{% for density in densities %}{{ ez_image_alias( field, versionInfo, parameters.alias~'_'~density ).uri }} {{ densitiesSizes&#91;loop.index0] }}{% if not loop.last %},{% endif %}{% endfor %}\"<\/span>\n                    {% endif %}\n            \/&gt;\n        {% endif %}\n    {% endspaceless %}\n{% endblock %}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>With the above, you will end up with a generated HTML something like this:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">         <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"ezimage-field\"<\/span>\n                <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/cloudinaryURL_for_myvariationname\u201d\n               srcset=\"<\/span>\n<span class=\"hljs-attr\">https:<\/span>\/\/<span class=\"hljs-attr\">cloudinaryURL_for_myvariationname_1px<\/span> <span class=\"hljs-attr\">640w<\/span>,\n<span class=\"hljs-attr\">https:<\/span>\/\/<span class=\"hljs-attr\">cloudinaryURL_for_myvariationname_2px<\/span> <span class=\"hljs-attr\">1040w<\/span>,\n<span class=\"hljs-attr\">https:<\/span>\/\/<span class=\"hljs-attr\">cloudinaryURL_for_myvariationname_3px<\/span> <span class=\"hljs-attr\">1560w<\/span>\"\n\/&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>That\u2019s it! If you want to know more about <code>srcset<\/code> and <code>sizes<\/code>, check out this great <a href=\"https:\/\/blog.ycombinator.com\/how-to-use-responsive-images\/\">ycombinator responsive images<\/a> article.<\/p>\n<h2>What\u2019s Next?<\/h2>\n<p>What\u2019s Next? Well, that\u2019s for you to determine. We invite you to create a <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">free Cloudinary account<\/a>, install the plugin, and start to play with the images on your eZ site.\nWe have a lot of big ideas for the next versions of this initial eZ-Cloudinary MVP, but first and foremost, we want to hear your ideas and see where you take it.<\/p>\n<p>You are all welcome to contribute!<\/p>\n<h2>About Novactive<\/h2>\n<p><a href=\"http:\/\/www.novactive.us\">Novactive (Nextedia Group)<\/a> is a web agency that develops digital platforms. Founded in 1996, Novactive is the brainchild of several web aficionados, whose combined vision of integrity and purpose drives every business decision. In 2016, Novactive joined the <a href=\"http:\/\/www.nextedia.com\/\">Nextedia Group<\/a>. Today Novactive with Nextedia is comprised of a highly experienced multidisciplinary team with more than 200 digital experts based in Paris, Toulon and San Francisco.<\/p>\n<img decoding=\"async\" src=\"https:\/\/cloudinary-res.cloudinary.com\/image\/upload\/w_100,f_auto\/Sebastien_Morel.jpg\" alt=\"S\u00e9bastien Morel Novactive CTO, head of U.S. operations and technology\" title=\"S\u00e9bastien Morel Novactive CTO, head of U.S. operations and technology\" style=\"float:left; margin-right:15px; margin-top: 10px;\">\n[S\u00e9bastien Morel](https:\/\/www.linkedin.com\/in\/sebastienmorel\/) is the CTO of Novactive, head of U.S. operations and technology, and runs the California office. S\u00e9bastien has been with the group for over 14 years.\n\u201cI love to take different web technologies and mix them together to get the best of them for our clients, but also to improve the developer and user experience. Open sourcing MVPs and packages is part of our core values. Sharing best practices and implementations, and allowing others to participate is THE way to build quality.\u201d\n<p>Novactive are part of Cloudinary\u2019s partnership network. We at Cloudinary value our partners. If you are interested to become a Cloudinary partner check out our <a href=\"https:\/\/cloudinary.com\/partners\">partnership program<\/a>.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":21629,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[59,98,165,229],"class_list":["post-21628","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-cms","tag-e-commerce","tag-image-transformation","tag-php"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Optimize images With Novactive eZ Platform Cloudinary plugin<\/title>\n<meta name=\"description\" content=\"Discover how connection of the eZ Platform CMS with Cloudinary can optimize images for great website performance.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Dynamic Image Manipulation and Optimization is eZ-er with the Novactive eZ Platform Cloudinary Connector\" \/>\n<meta property=\"og:description\" content=\"Discover how connection of the eZ Platform CMS with Cloudinary can optimize images for great website performance.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-11-08T17:43:16+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-01T17:50:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100-png?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"1540\" \/>\n\t<meta property=\"og:image:height\" content=\"847\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Dynamic Image Manipulation and Optimization is eZ-er with the Novactive eZ Platform Cloudinary Connector\",\"datePublished\":\"2017-11-08T17:43:16+00:00\",\"dateModified\":\"2024-06-01T17:50:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1\"},\"wordCount\":14,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100.png?_i=AA\",\"keywords\":[\"CMS\",\"E-commerce\",\"Image Transformation\",\"PHP\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2017\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1\",\"url\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1\",\"name\":\"Optimize images With Novactive eZ Platform Cloudinary plugin\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100.png?_i=AA\",\"datePublished\":\"2017-11-08T17:43:16+00:00\",\"dateModified\":\"2024-06-01T17:50:43+00:00\",\"description\":\"Discover how connection of the eZ Platform CMS with Cloudinary can optimize images for great website performance.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100.png?_i=AA\",\"width\":1540,\"height\":847},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Dynamic Image Manipulation and Optimization is eZ-er with the Novactive eZ Platform Cloudinary Connector\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Optimize images With Novactive eZ Platform Cloudinary plugin","description":"Discover how connection of the eZ Platform CMS with Cloudinary can optimize images for great website performance.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1","og_locale":"en_US","og_type":"article","og_title":"Dynamic Image Manipulation and Optimization is eZ-er with the Novactive eZ Platform Cloudinary Connector","og_description":"Discover how connection of the eZ Platform CMS with Cloudinary can optimize images for great website performance.","og_url":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1","og_site_name":"Cloudinary Blog","article_published_time":"2017-11-08T17:43:16+00:00","article_modified_time":"2024-06-01T17:50:43+00:00","og_image":[{"width":1540,"height":847,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100-png?_i=AA","type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1"},"author":{"name":"","@id":""},"headline":"Dynamic Image Manipulation and Optimization is eZ-er with the Novactive eZ Platform Cloudinary Connector","datePublished":"2017-11-08T17:43:16+00:00","dateModified":"2024-06-01T17:50:43+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1"},"wordCount":14,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100.png?_i=AA","keywords":["CMS","E-commerce","Image Transformation","PHP"],"inLanguage":"en-US","copyrightYear":"2017","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1","url":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1","name":"Optimize images With Novactive eZ Platform Cloudinary plugin","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100.png?_i=AA","datePublished":"2017-11-08T17:43:16+00:00","dateModified":"2024-06-01T17:50:43+00:00","description":"Discover how connection of the eZ Platform CMS with Cloudinary can optimize images for great website performance.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100.png?_i=AA","width":1540,"height":847},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/dynamic_image_manipulation_and_optimization_is_ez_er_with_the_novactive_ez_platform_cloudinary_connector1#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Dynamic Image Manipulation and Optimization is eZ-er with the Novactive eZ Platform Cloudinary Connector"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649723741\/Web_Assets\/blog\/Connector_2000x1100\/Connector_2000x1100.png?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21628","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=21628"}],"version-history":[{"count":4,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21628\/revisions"}],"predecessor-version":[{"id":34223,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/21628\/revisions\/34223"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/21629"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=21628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=21628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=21628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}