{"id":31170,"date":"2023-09-18T07:00:00","date_gmt":"2023-09-18T14:00:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=31170"},"modified":"2025-02-23T15:22:22","modified_gmt":"2025-02-23T23:22:22","slug":"image-optimization-headless-wordpress-wpgraphql","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql","title":{"rendered":"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL"},"content":{"rendered":"\n<p>Image optimization is important in delivering an efficient user experience in web development. The integration of WordPress as a headless CMS with front-end technologies has empowered developers to build responsive and dynamic web applications. However, managing and optimizing images within this headless architecture has its challenges.<\/p>\n\n\n\n<p>The Cloudinary WordPress plugin and WPGraphQL are two tools that combine to offer a streamlined solution for <a href=\"https:\/\/cloudinary.com\/guides\/wordpress-plugin\/the-top-9-plugins-to-optimize-images-in-wordpress\" target=\"_blank\" rel=\"noreferrer noopener\">image optimization<\/a>. WPGraphQL provides a flexible query language, enabling developers to request only the data they need in your WordPress backend, while Cloudinary&#8217;s plugin offers a suite of features to handle image transformations, compression, and delivery in WordPress.<\/p>\n\n\n\n<p>In this article, we\u2019ll explore the techniques for image optimization within a headless WordPress environment. We&#8217;ll delve into the setup and configuration of WPGraphQL, integrating it with the Cloudinary WordPress plugin, and demonstrate how to use these tools to achieve optimal image performance.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Getting Started<\/h2>\n\n\n\n<p>To benefit from this article, you should be familiar with the basics of WordPress development, WPGraphQL, <a href=\"https:\/\/nodejs.org\/en\" target=\"_blank\" rel=\"noreferrer noopener\">Node.js<\/a>, <a href=\"https:\/\/nextjs.org\/\" target=\"_blank\" rel=\"noreferrer noopener\">Next.js<\/a>, and the<a href=\"https:\/\/www.apollographql.com\/docs\/\" target=\"_blank\" rel=\"noreferrer noopener\"> Apollo Client<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Steps for Local Development Setup<\/h3>\n\n\n\n<p>WordPress setup:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Set up a WordPress site on any host of your choice. I\u2019m using <a href=\"https:\/\/localwp.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Local by WP Engine, which is a free local development server for WordPress.<\/a><\/li>\n\n\n\n<li>Install and <a href=\"https:\/\/cloudinary.com\/documentation\/wordpress_integration\" target=\"_blank\" rel=\"noreferrer noopener\">activate the Cloudinary plugin<\/a>.<\/li>\n\n\n\n<li>Install and <a href=\"https:\/\/www.wpgraphql.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">activate the WPGraphQL plugin<\/a>.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Next.js\/Faust.js Setup<\/h3>\n\n\n\n<p>For this article, I\u2019ll use Faust.js, a frontend framework built on top of Next.js, specifically designed to work with headless WordPress. Out of the box, it has the Apollo Client, WPGraphQL and basic queries as well as routing built in.<\/p>\n\n\n<div class='c-callout  c-callout--inline-title c-callout--note'><strong class='c-callout__title'>Note:<\/strong> <p>If you\u2019re using Local and follow the setup wizard, it has an option to spin up a Faust.js project from Local. This will automate the connection with your WordPress environment variables and Faust.js.<\/p>\n<\/div>\n\n\n<p>If you want to use a Faust.js project off npm, you can follow the <a href=\"https:\/\/faustjs.org\/tutorial\/get-started-with-faust\" target=\"_blank\" rel=\"noreferrer noopener\">getting started documentation here.<\/a><\/p>\n\n\n\n<p>If you choose to use Next.js on its own, you can follow along in the custom Next.js section of this article <a href=\"https:\/\/github.com\/colbyfayock\/next-wpgraphql-basic-starter\" target=\"_blank\" rel=\"noreferrer noopener\">using my good friend Colby Fayock\u2019s starter project here<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Cloudinary WordPress Plugin<\/h2>\n\n\n\n<p>The Cloudinary WordPress plugin integrates Cloudinary&#8217;s image and video management services with WordPress. Here&#8217;s a detailed breakdown of its functions:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Image optimization.<\/strong> The plugin can automatically optimize images, transforming their format and quality to improve loading times without compromising visual appearance.<\/li>\n\n\n\n<li><strong>Responsive images. <\/strong>Cloudinary can automatically create various resized versions of each image, ensuring that the optimal size is delivered for every device and screen resolution.<\/li>\n\n\n\n<li><strong>Media management. <\/strong>Through the plugin, Cloudinary&#8217;s media library can be accessed directly within WordPress, enabling efficient management, organization, and transformation of media files.<\/li>\n\n\n\n<li><strong>Content delivery network (CDN) integration.<\/strong> Images and videos are served via Cloudinary&#8217;s globally distributed CDN. This ensures faster delivery to users around the world.<\/li>\n\n\n\n<li><strong>Video manipulation. <\/strong>Not just limited to images, Cloudinary also allows transformation and optimization of video content. Videos can be resized, cropped, filtered, and much more.<\/li>\n\n\n\n<li><strong>Accessibility enhancements. <\/strong>The plugin can automatically add attributes like alt text, assisting in meeting various accessibility standards.<\/li>\n\n\n\n<li><strong>Easy integration with visual editors.<\/strong> It&#8217;s generally compatible with popular WordPress visual editors and page builders, allowing seamless insertion and transformation of images and videos.<\/li>\n\n\n\n<li><strong>Developer-friendly options.<\/strong> For developers, the Cloudinary API can be used to create custom transformations and integrations.<\/li>\n\n\n\n<li><strong>Analytics and insights.<\/strong> Cloudinary offers insights into media asset performance and usage, which can help in understanding how media is being accessed and utilized.<\/li>\n<\/ul>\n\n\n\n<p>In a headless WordPress context, the Cloudinary plugin can be utilized to ensure that media is managed efficiently, optimized, and delivered in the most responsive manner.<\/p>\n\n\n\n<p>Now that we have it installed in our WP Admin, after you follow the setup wizard, you should have a main dashboard that looks like this:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/sIn1_TfjPlADaa-MCxI1sz41Acl-oTsYzkOnF4JDylim9vHvSp6Xe7Ixz-Twp2ph_bAmLwkLCvYBY6IpkTgzt7_-F15eRhupF23O3lpso_rl2k8nA1P-LunYIMoey1jEVdhAWou_6hLRjdbS4UrqDyI\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>Once downloaded, the default settings and media sync is automatic. Your media items are now offloaded to an optimized media CDN!<\/p>\n\n\n\n<p>It\u2019s that easy. If you go to your media option on the side menu in your WP Admin and start loading in images, the Cloudinary plugin will automatically sync your images to the Cloudinary CDN as well as your dashboard:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/RL9uppLEdc9ZDWQcc6fRandxgI3Er1QvIxOUAJZxotg4qQ7pMcYRnDyclqNwGSnBwJ0vS6NH2xxDGyTlgBDE2EGhnj6zufPlUTwjpet-OCrc18lX7H3eCXk-RopcDxdsprvYiaYEWOgSDsPRJ3DYqTQ\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>The green cloud icon indicates that the sync is successful between your WordPress backend and your Cloudinary account.<\/p>\n\n\n\n<p>A feature I want to highlight is the Cloudinary DAM, which is an extension. Once you select<strong> Add Extension<\/strong> in the dashboard here:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/s4ere4I6eDnOSeNg_SJVCii1_XS1fp09xuw_UBUMmuEIGYFFbuIfDQcCTYsxF3Zm5ss1T7gxg_CZOoEVqGDwjyXYiyRm0zbrs4pDUseNWz2HQbE6DmQktKeEDr9FiMD-ELuXAFAY-tyIsVguUPHpmlg\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>It will give you access to your media library and the features you have that you similarly have in your Cloudinary console. This is awesome as it eliminates having to switch back and forth from WP admin to your Cloudinary console.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">WPGraphQL<\/h2>\n\n\n\n<p>WPGrahQL is an open source WordPress plugin that turns your WordPress backend into a GraphQL server. Once you download this plugin, you\u2019ll have a menu on the right side of your WP Admin relating to your WPGraphQL settings as well as a GraphiQL IDE.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/P3lpd3QOpZgSVrVUvrFKXNHxiI0VxdtHR--mMcN7VFSMeWwPay-ePHE17Hjf6vEpLZZWqX_rbDJwpFxRRH3-rBoAGiHHo6JTYQP8Vfhckf0U3qSS9M7rEDevThVjBYJF09yJCGnRc63y_PTNMNoyVmE\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/OkuaFgGrFjY4MkhnhyCxft1Gd6sjNgieRqZhnlW-YzWj_HDCEY4w3DzD5M2INzBvfWNdZmMAaB4VIwa27Ut6rcjh8KTyvoEVs6E_q9S_BDCuhgXeXgqzZtuOcBrQOXQBsEBAkslbbsE9iBPe3gxFXFM\" alt=\"\"\/><\/figure>\n\n\n\n<p>Now that WPGraphQL is set up, let&#8217;s make a query for the featured images of all our posts:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">{\n  posts {\n    nodes{\n      featuredImage {\n        node {\n          sourceUrl\n        }\n      }\n    }\n  }\n}\n<\/code><\/span><\/pre>\n\n\n<p>This is the data we get back from that request:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/4TVFpVcJX8KhCYs6zTgYoBBnQEbCDRtq81B__GIiEo1vsNpjahcV_a2Wcw0tRA-nw6_F3idCnxmMaSBS9mE4vXa-ejYQW1WDVW8_pTAo5Fb_qWvgfCG1RZ_0TVemRF_oHnXGkOgaUk7U3H0fdgQZtGs\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>The source URL of that image is being served from the Cloudinary CDN instead of WordPress.<\/p>\n\n\n\n<p>Now let\u2019s query for images within the block editor in WordPress that aren\u2019t the featured image.&nbsp; You can do this by downloading the extension for WPGraphQL to <a href=\"https:\/\/github.com\/wpengine\/wp-graphql-content-blocks\" target=\"_blank\" rel=\"noreferrer noopener\">query content blocks called WPGraphQL Content Blocks.<\/a><\/p>\n\n\n\n<p>Here\u2019s our query:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">{\n  posts {\n    nodes {\n      editorBlocks {\n        ... on CoreImage {\n          apiVersion\n          attributes {\n            url\n          }\n        }\n      }\n    }\n  }\n}\n<\/code><\/span><\/pre>\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/4FPR3QIoM8ckP8nfZtb-DlLGDUEXUGBTDH5_-FemtohW1iOEGKWmM_i9NHV-ugtlnsjbmpkSJQwaMDNa1vvcWC86EmYPKzp7fZzZqYZ3DRudFMc0zqzEFAiszmNWrv41i5f-EP26L1dnmMDGIzRVotI\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>The image shows we get back the data from the blocks with images, and it\u2019s also coming from Cloudinary. Just a note, I also added some content to these posts along with images.<\/p>\n\n\n\n<p>Now that we\u2019ve offloaded and optimized our images to Cloudinary in our WordPress backend, let\u2019s render that data on the front end with Faust.js.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Image Optimization on the Frontend<\/h2>\n\n\n\n<p>We have our queries coming back from WPGraphQL with the images in our WordPress backend being offset to the Cloudinary CDN. Because we\u2019re using Faust.js for our frontend, it automatically has the components and the queries built in to render the post\u2019s data you input in its boilerplate.&nbsp;&nbsp;<\/p>\n\n\n\n<p>Let\u2019s take a look at our browser now running on localhost:3000<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/7VtM7ZBtU6WbIOJko8NnbvLYDWSwov-cRdKLXjHSsMuim7ZGQxHG4q7X4UwOee3QDUlEGetc0VtKYhSgKt5i-OpySnPySvDY3c-RZEVzqT6oSxjLMJYPX0h3c4fn26Hx9PrJCtAWUsFdmzY_hbF3oco\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>We have our images from our posts in our WordPress backend on the page. Now, let&#8217;s open up the dev tools and look at the elements tab:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/NEk8H1KTMRcdGLlYLjWbRp_plEr_E3WJqUxCtCCJT19Y1hSzPZGqMIPEGTHnOWc2ajQMcHXFBgeItR10bserh3jZvo2vjj501U2ZEoPAydBwupti5UuC4TF3e_cA7GthwOhrYKGfczkIyEWKHGctz8M\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>You can see that on the browser, the images are coming from the Cloudinary CDN as well as the Cloudinary lazy loading script to optimize those images when necessary.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Custom Next.js Pages<\/h2>\n\n\n\n<p>If you\u2019re using only Next.js, let\u2019s create a custom page that pulls out only images.<\/p>\n\n\n<div class='c-callout  c-callout--inline-title c-callout--note'><strong class='c-callout__title'>Note:<\/strong> <p>You can also do this in Faust.js as it\u2019s built on top of Next.js.<\/p>\n<\/div>\n\n\n<p>First, create a components directory in your Next.js project at the root. In the components directory, add a <code>ImageComponent.js<\/code> file then paste this code in:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> { useQuery, gql } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@apollo\/client\"<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> GET_ALL_IMAGES_FROM_BLOCKS = gql<span class=\"hljs-string\">`\n  {\n    posts {\n      nodes {\n        featuredImage {\n          node {\n            sourceUrl\n            altText\n          }\n        }\n        editorBlocks {\n          ... on CoreImage {\n            apiVersion\n            attributes {\n              url\n            }\n          }\n        }\n      }\n    }\n  }\n`<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> ImagesFromPosts = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">const<\/span> { loading, error, data } = useQuery(GET_ALL_IMAGES_FROM_BLOCKS);\n\n  <span class=\"hljs-keyword\">if<\/span> (loading) <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Loading...<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n  <span class=\"hljs-keyword\">if<\/span> (error) <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Error: {error.message}<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span><\/span>;\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">display:<\/span> \"<span class=\"hljs-attr\">flex<\/span>\", <span class=\"hljs-attr\">flexWrap:<\/span> \"<span class=\"hljs-attr\">wrap<\/span>\", <span class=\"hljs-attr\">gap:<\/span> \"<span class=\"hljs-attr\">10px<\/span>\" }}&gt;<\/span>\n      {data.posts.nodes.map((post, index) =&gt; (\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{index}<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">width:<\/span> \"<span class=\"hljs-attr\">30<\/span>%\" }}&gt;<\/span>\n          {post.featuredImage?.node &amp;&amp; (\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n              <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{post.featuredImage.node.sourceUrl}<\/span>\n              <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">{post.featuredImage.node.altText<\/span> || \"\"}\n              <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">width:<\/span> \"<span class=\"hljs-attr\">100<\/span>%\", <span class=\"hljs-attr\">marginBottom:<\/span> \"<span class=\"hljs-attr\">10px<\/span>\" }}\n            \/&gt;<\/span>\n          )}\n          {post.editorBlocks.map((block, blockIndex) =&gt; {\n            if (block.__typename === \"CoreImage\" &amp;&amp; block.attributes.url) {\n              return (\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span>\n                  <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{blockIndex}<\/span>\n                  <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{block.attributes.url}<\/span>\n                  <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"\"<\/span>\n                  <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">width:<\/span> \"<span class=\"hljs-attr\">100<\/span>%\", <span class=\"hljs-attr\">marginBottom:<\/span> \"<span class=\"hljs-attr\">10px<\/span>\" }}\n                \/&gt;<\/span>\n              );\n            }\n            return null;\n          })}\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n      ))}\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> ImagesFromPosts;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><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\n\n<p>Let\u2019s break down what\u2019s happening in this component:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <code>GET_ALL_IMAGES_FROM_BLOCKS<\/code> GraphQL query matches the one provided, targeting images from content blocks. Within the query, I\u2019m asking for the featured images of all posts as well as core images of blocks.<\/li>\n\n\n\n<li>The <code>useQuery<\/code> hook from Apollo Client is used to execute the query.<\/li>\n\n\n\n<li>Loading and error states are handled appropriately.<\/li>\n\n\n\n<li>The images are mapped over and rendered as <code>&lt;img&gt;<\/code> elements.<\/li>\n<\/ul>\n\n\n\n<p>You can import and use this component within your pages or other components in your Next.js project.<\/p>\n\n\n<div class='c-callout  c-callout--inline-title c-callout--note'><strong class='c-callout__title'>Note:<\/strong> <p>Since the provided query doesn\u2019t include an alt attribute for the images, I\u2019ve left the alt attribute of the <code>&lt;img&gt;<\/code> tags empty. If possible, including an appropriate alt attribute would improve accessibility. I just didn\u2019t do it for this article.<\/p>\n<\/div>\n\n\n<p>Then, in the pages directory of your Next.js project, create a file called <code>images.js<\/code> and paste this code in:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">images<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ImagesComponent<\/span> \/&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/&gt;<\/span><\/span>\n  );\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><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\n\n<p>This component is rendering the <code>ImagesComponent<\/code> inside a div. Let\u2019s see what we get on the browser:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/hSheM8Ij5bqlDAVI3yJvmRftZFDcdhJk_Ddj39S6pVcztCpg0S_U2K01FVGXfW4uMPd51rGtbbOZ-XEtJP9zdE0TwZhvAi3t5HM713qy7N7c_pi8xwCOEVCjKhw0h6QX_kU-sAoIREkfrbeNNT6qIR8\" alt=\"\"\/><\/figure><\/div>\n\n\n<p>We get back all our images from our WordPress backend being served by Cloudinary!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>I hope this article provided a better understanding for you in using the Cloudinary WordPress plugin with WPGraphQL in headless.<\/p>\n\n\n\n<p>As always, I look forward to seeing what you build out there on the web and if you have any feedback, please share in the <a href=\"https:\/\/community.cloudinary.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary Community<\/a> forums or the associated <a href=\"https:\/\/discord.gg\/cloudinary\" target=\"_blank\" rel=\"noreferrer noopener\">Discord<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Image optimization is important in delivering an efficient user experience in web development. The integration of WordPress as a headless CMS with front-end technologies has empowered developers to build responsive and dynamic web applications. However, managing and optimizing images within this headless architecture has its challenges. The Cloudinary WordPress plugin and WPGraphQL are two tools [&hellip;]<\/p>\n","protected":false},"author":87,"featured_media":31173,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[370,227],"class_list":["post-31170","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-image","tag-performance-optimization"],"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>Image Optimization in Headless WordPress With Cloudinary and WPGraphQL<\/title>\n<meta name=\"description\" content=\"Image optimization is important in delivering an efficient user experience in web development. The integration of WordPress as a headless CMS with\" \/>\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\/image-optimization-headless-wordpress-wpgraphql\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL\" \/>\n<meta property=\"og:description\" content=\"Image optimization is important in delivering an efficient user experience in web development. The integration of WordPress as a headless CMS with\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-09-18T14:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-02-23T23:22:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL-jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"melindapham\" \/>\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\/image-optimization-headless-wordpress-wpgraphql#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL\",\"datePublished\":\"2023-09-18T14:00:00+00:00\",\"dateModified\":\"2025-02-23T23:22:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql\"},\"wordCount\":1311,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL.jpg?_i=AA\",\"keywords\":[\"Image\",\"Performance Optimization\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2023\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql\",\"url\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql\",\"name\":\"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL.jpg?_i=AA\",\"datePublished\":\"2023-09-18T14:00:00+00:00\",\"dateModified\":\"2025-02-23T23:22:22+00:00\",\"description\":\"Image optimization is important in delivering an efficient user experience in web development. The integration of WordPress as a headless CMS with\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL.jpg?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL\"}]},{\"@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\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\",\"name\":\"melindapham\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"caption\":\"melindapham\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL","description":"Image optimization is important in delivering an efficient user experience in web development. The integration of WordPress as a headless CMS with","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\/image-optimization-headless-wordpress-wpgraphql","og_locale":"en_US","og_type":"article","og_title":"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL","og_description":"Image optimization is important in delivering an efficient user experience in web development. The integration of WordPress as a headless CMS with","og_url":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql","og_site_name":"Cloudinary Blog","article_published_time":"2023-09-18T14:00:00+00:00","article_modified_time":"2025-02-23T23:22:22+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL-jpg?_i=AA","type":"image\/jpeg"}],"author":"melindapham","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL","datePublished":"2023-09-18T14:00:00+00:00","dateModified":"2025-02-23T23:22:22+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql"},"wordCount":1311,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL.jpg?_i=AA","keywords":["Image","Performance Optimization"],"inLanguage":"en-US","copyrightYear":"2023","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql","url":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql","name":"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL.jpg?_i=AA","datePublished":"2023-09-18T14:00:00+00:00","dateModified":"2025-02-23T23:22:22+00:00","description":"Image optimization is important in delivering an efficient user experience in web development. The integration of WordPress as a headless CMS with","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL.jpg?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/image-optimization-headless-wordpress-wpgraphql#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Image Optimization in Headless WordPress With Cloudinary and WPGraphQL"}]},{"@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":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9","name":"melindapham","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","caption":"melindapham"}}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1692896219\/Blog-WP-GraphQL\/Blog-WP-GraphQL.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/31170","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\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=31170"}],"version-history":[{"count":8,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/31170\/revisions"}],"predecessor-version":[{"id":36989,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/31170\/revisions\/36989"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/31173"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=31170"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=31170"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=31170"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}