{"id":8001,"date":"2025-06-11T10:53:25","date_gmt":"2025-06-11T03:53:25","guid":{"rendered":"https:\/\/danielepais.com\/journal\/?p=8001"},"modified":"2025-06-11T11:16:37","modified_gmt":"2025-06-11T04:16:37","slug":"wordpress-custom-cta-plugin-build-customize-your-own","status":"publish","type":"post","link":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/","title":{"rendered":"WordPress Custom CTA Plugin: Build &#038; Customize Your Own"},"content":{"rendered":"<p data-sourcepos=\"9:1-9:245\">Master custom CTA plugin development for <a href=\"https:\/\/danielepais.com\/journal\/build-a-multi-language-floating-newsletter-button-as-a-wordpress-mu-plugin\/\">WordPress<\/a>. This tutorial guides you to build powerful, customizable CTAs with color pickers, images &amp; shortcodes. Gain full control!<\/p>\n<p data-sourcepos=\"9:1-9:245\"><img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/0fa5d7471ea0\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/e27e8ca72651\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/b99c4deff3fe\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/35c42fc798ea\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/7efdb114c9e9\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/ce4a51865de8\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/024d7fedcd83\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/125ddd7b4cf0\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/d364fbac00ca\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/c71e9181d7a8\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/7730fe5c6e54\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"alignnone size-full wp-image-8024\" title=\"WordPress Custom CTA Plugin\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9Xb3JkUHJlc3MtQ3VzdG9tLUNUQS1QbHVnaW4uanBn\/323e9d989bcd\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"WordPress Custom CTA Plugin\" width=\"850\" height=\"400\" \/><\/p>\n<p data-sourcepos=\"9:1-9:245\">Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors to their very appearance, all managed in one central place?<\/p>\n<p data-sourcepos=\"11:1-11:51\">If you answered yes, then this tutorial is for you!<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6ac7fcd7801f1\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #18bc9c;color:#18bc9c\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #18bc9c;color:#18bc9c\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6ac7fcd7801f1\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#Master_Your_CTAs_Build_a_Dynamic_Customizable_WordPress_Plugin\" >Master Your CTAs: Build a Dynamic &amp; Customizable WordPress Plugin<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#Section_1_Setting_Up_Your_Plugin_Base\" >Section 1: Setting Up Your Plugin Base<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#Section_2_Crafting_the_Admin_Settings_Page\" >Section 2: Crafting the Admin Settings Page<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#Section_3_Enqueuing_Styles_and_Scripts\" >Section 3: Enqueuing Styles and Scripts<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#Section_4_The_Activation_Hook_%E2%80%93_Auto-Generating_Assets\" >Section 4: The Activation Hook &#8211; Auto-Generating Assets<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#Section_5_Displaying_Your_CTAs_with_Shortcodes\" >Section 5: Displaying Your CTAs with Shortcodes<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#Section_6_Final_Touches_Best_Practices\" >Section 6: Final Touches &amp; Best Practices<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#One_Last_Tip\" >One Last Tip<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#Conclusion_Empowering_Your_WordPress_Site\" >Conclusion: Empowering Your WordPress Site<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#5_Minutes_Tutorial\" >5 Minutes Tutorial<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h2 data-sourcepos=\"11:1-11:51\"><span class=\"ez-toc-section\" id=\"Master_Your_CTAs_Build_a_Dynamic_Customizable_WordPress_Plugin\"><\/span>Master Your CTAs: Build a Dynamic &amp; Customizable WordPress Plugin<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<figure id=\"attachment_8020\" aria-describedby=\"caption-attachment-8020\" style=\"width: 1107px\" class=\"wp-caption aligncenter\"><img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/e26335f219f0\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/5a2007176f7c\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/024508cd1971\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/db6299b0f00c\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/c012d17e73bb\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/fe76e2a0b920\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/ef9f0797c3b2\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/26734ea047a2\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/e0194ec6e66a\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/b9f1ee1de39d\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/0cf26f1b7f21\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"wp-image-8020 size-full\" title=\"test Phuket Web Design 06 11 2025 01 45 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfNDVfQU0uanBn\/59c13154684a\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"test Phuket Web Design 06 11 2025 01 45 AM\" width=\"1107\" height=\"435\" \/><figcaption id=\"caption-attachment-8020\" class=\"wp-caption-text\"><strong>HERE IS AN EXAMPLE OF HOW THE CTA WILL LOOK LIKE<\/strong><\/figcaption><\/figure>\n<p data-sourcepos=\"13:1-13:216\">In this in-depth guide, we&#8217;re going to build a custom WordPress plugin from scratch. This isn&#8217;t just a simple shortcode; we&#8217;re creating a robust, site-wide customizable CTA management system that will empower you to:<\/p>\n<ul data-sourcepos=\"15:1-20:0\">\n<li data-sourcepos=\"15:1-15:64\">Create\u00a0<strong>multiple, unique CTA blocks<\/strong>\u00a0for different purposes.<\/li>\n<li data-sourcepos=\"16:1-16:107\">Include\u00a0<strong>images, prominent titles, catchy subtitles, descriptive paragraphs<\/strong>, and engaging\u00a0<strong>buttons<\/strong>.<\/li>\n<li data-sourcepos=\"17:1-17:104\"><strong><span class=\"citation-34\">Visually pick button background and text colors<\/span><\/strong><span class=\"citation-34 citation-end-34\">\u00a0directly from your WordPress admin.<\/span><\/li>\n<li data-sourcepos=\"18:1-18:81\">Display your beautiful CTAs anywhere on your site using a simple\u00a0<strong>shortcode<\/strong>.<\/li>\n<li data-sourcepos=\"19:1-20:0\">Apply\u00a0<strong>stunning custom styling<\/strong>\u00a0with enhanced image shadows, elegant frames, and smooth button hover effects.<\/li>\n<\/ul>\n<p data-sourcepos=\"21:1-21:55\"><img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/9b33bc33219f\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/f1c87bad4aa9\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/c2e137a43cec\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/2e4193210717\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/26255b2933e9\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/1858d4b31db3\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/c930e950d48b\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/e58821f59a4f\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/2444c6dd03da\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/17ff36edb60b\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/dd471cddf82e\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"aligncenter size-full wp-image-8006\" title=\"Plugins \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 12 51 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9QbHVnaW5zLeKAuS1QaHVrZXQtV2ViLURlc2lnbi3igJQtV29yZFByZXNzLTA2LTExLTIwMjVfMTJfNTFfQU0uanBn\/55378ff92d7f\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"Plugins \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 12 51 AM\" width=\"1601\" height=\"107\" \/><\/p>\n<p data-sourcepos=\"21:1-21:55\">Let&#8217;s dive in and take control of your Call-to-Actions!<\/p>\n<hr data-sourcepos=\"23:1-23:3\" \/>\n<h2 data-sourcepos=\"25:1-25:42\"><span class=\"ez-toc-section\" id=\"Section_1_Setting_Up_Your_Plugin_Base\"><\/span>Section 1: Setting Up Your Plugin Base<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p data-sourcepos=\"27:1-27:89\"><span class=\"citation-33 citation-end-33\">Every WordPress plugin starts with a dedicated folder and a main PHP file.<\/span><\/p>\n<p data-sourcepos=\"29:1-29:55\"><strong>Step 1.1: Create Your Plugin Folder &amp; Main File<\/strong><\/p>\n<p data-sourcepos=\"31:1-31:172\">First, connect to your WordPress site using an FTP client (like FileZilla) or through your hosting provider&#8217;s File Manager. Navigate to the\u00a0<code>wp-content\/plugins\/<\/code>\u00a0directory.<\/p>\n<p data-sourcepos=\"33:1-33:72\">Inside\u00a0<code>wp-content\/plugins\/<\/code>, create a new folder named\u00a0<code>my-custom-cta<\/code>.<\/p>\n<p data-sourcepos=\"35:1-35:125\">Now, inside this\u00a0<code>my-custom-cta<\/code>\u00a0folder, create a new PHP file named\u00a0<code>my-custom-cta.php<\/code>. This will be your main plugin file.<\/p>\n<p data-sourcepos=\"37:1-37:116\">Open\u00a0<code>my-custom-cta.php<\/code>\u00a0and add the following basic plugin header comments. This tells WordPress about your plugin.<\/p>\n<p data-sourcepos=\"37:1-37:116\"><pre id=\"code-snippet-source-72\" class=\"code-snippet-source linkable-line-numbers\"><code class=\"language-php line-numbers\">&lt;?php\n\/*\nPlugin Name: My Custom CTA\nPlugin URI:  https:\/\/example.com\/\nDescription: A simple WordPress plugin to create, manage, and display multiple Call-to-Action blocks via shortcodes.\nVersion:     1.3\nAuthor:      Your Name\nAuthor URI:  https:\/\/example.com\/\nLicense:     GPL2\nLicense URI: https:\/\/www.gnu.org\/licenses\/gpl-2.0.html\nText Domain: my-custom-cta\n*\/\n\nif ( ! defined( &#039;ABSPATH&#039; ) ) {\n    exit; \/\/ Exit if accessed directly\n}\n\n\/\/ Your plugin code will go here<\/code><\/pre>\n<p data-sourcepos=\"60:1-60:35\"><strong>Step 1.2: The Core Plugin Class<\/strong><\/p>\n<p data-sourcepos=\"62:1-62:152\">We&#8217;ll structure our plugin using an object-oriented approach with a main class. This keeps our code organized and prevents conflicts with other plugins.<\/p>\n<p data-sourcepos=\"64:1-64:104\">Below the initial comments and the <code>if ( ! defined( 'ABSPATH' ) )<\/code> block, add the basic class structure:<\/p>\n<p data-sourcepos=\"64:1-64:104\"><pre id=\"code-snippet-source-73\" class=\"code-snippet-source linkable-line-numbers\"><code class=\"language-php line-numbers\">\/\/ ... (previous code) ...\n\n\/**\n * My Custom CTA Class\n *\/\nclass My_Custom_CTA {\n\n    private $option_name = &#039;my_custom_ctas&#039;; \/\/ Option name to store all CTAs\n\n    public function __construct() {\n        \/\/ WordPress Hooks go here to initiate plugin functionality\n        add_action( &#039;admin_menu&#039;, array( $this, &#039;add_admin_menu&#039; ) );\n        add_action( &#039;admin_init&#039;, array( $this, &#039;register_settings&#039; ) );\n        add_action( &#039;admin_enqueue_scripts&#039;, array( $this, &#039;enqueue_admin_scripts&#039; ) );\n        add_action( &#039;wp_enqueue_scripts&#039;, array( $this, &#039;enqueue_frontend_styles&#039; ) );\n        add_shortcode( &#039;my_custom_cta&#039;, array( $this, &#039;render_cta_shortcode&#039; ) );\n    }\n\n    \/\/ All our plugin methods will be defined below this constructor\n\n} \/\/ End of My_Custom_CTA class\n\nnew My_Custom_CTA(); \/\/ Initialize the plugin<\/code><\/pre>\n<p data-sourcepos=\"92:1-92:112\">The <code>__construct()<\/code> method is like the plugin&#8217;s initializer. Here, we&#8217;re hooking into various WordPress actions:<\/p>\n<ul data-sourcepos=\"93:1-98:0\">\n<li data-sourcepos=\"93:1-93:84\"><code><span class=\"citation-29\">admin_menu<\/span><\/code><span class=\"citation-29 citation-end-29\">: To add our settings page to the WordPress admin menu.<\/span>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<li data-sourcepos=\"94:1-94:65\"><code><span class=\"citation-28\">admin_init<\/span><\/code><span class=\"citation-28 citation-end-28\">: To register our plugin&#8217;s settings.<\/span>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<li data-sourcepos=\"95:1-95:101\"><code><span class=\"citation-27\">admin_enqueue_scripts<\/span><\/code><span class=\"citation-27 citation-end-27\">: To load CSS and JavaScript specifically for our admin page.<\/span>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<li data-sourcepos=\"96:1-96:89\"><code><span class=\"citation-26\">wp_enqueue_scripts<\/span><\/code><span class=\"citation-26 citation-end-26\">: To load CSS for the front-end display of our CTAs.<\/span>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<li data-sourcepos=\"97:1-98:0\"><code><span class=\"citation-25\">add_shortcode<\/span><\/code><span class=\"citation-25 citation-end-25\">: To register the shortcode users will use to display CTAs.<\/span>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<\/ul>\n<hr data-sourcepos=\"99:1-99:3\" \/>\n<h2 data-sourcepos=\"101:1-101:47\"><span class=\"ez-toc-section\" id=\"Section_2_Crafting_the_Admin_Settings_Page\"><\/span>Section 2: Crafting the Admin Settings Page<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p data-sourcepos=\"103:1-103:59\"><img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/1a9bc7431958\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/a51427211c19\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/5bcbdb7d062a\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/bf7b1bdd11cd\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/602ee89395aa\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/a6844ccc28ae\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/4f7a18e45ce4\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/ea665d135fbf\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/85f6e6ccfa61\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/4640cb29c7a4\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/2908d1df2778\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"alignright size-full wp-image-8009\" title=\"Dashboard \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 12 55 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9EYXNoYm9hcmQt4oC5LVBodWtldC1XZWItRGVzaWduLeKAlC1Xb3JkUHJlc3MtMDYtMTEtMjAyNV8xMl81NV9BTS5qcGc\/cc8b8c04f9ba\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"Dashboard \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 12 55 AM\" width=\"192\" height=\"461\" \/>This is where you&#8217;ll create and manage all your CTA blocks.<\/p>\n<p data-sourcepos=\"105:1-105:31\"><strong>Step 2.1: Add the Menu Item<\/strong><\/p>\n<p data-sourcepos=\"107:1-107:67\">Inside your <code>My_Custom_CTA<\/code> class, add the <code>add_admin_menu<\/code> method:<\/p>\n<p data-sourcepos=\"107:1-107:67\"><pre id=\"code-snippet-source-74\" class=\"code-snippet-source linkable-line-numbers\"><code class=\"language-php line-numbers\">\/\/ ... (inside My_Custom_CTA class) ...\n\n    \/**\n     * Add admin menu page\n     *\/\n    public function add_admin_menu() {\n        add_menu_page(\n            __( &#039;My Custom CTAs&#039;, &#039;my-custom-cta&#039; ), \/\/ Page title\n            __( &#039;Custom CTAs&#039;, &#039;my-custom-cta&#039; ),    \/\/ Menu title\n            &#039;manage_options&#039;,                        \/\/ Capability required\n            &#039;my-custom-cta&#039;,                         \/\/ Menu slug\n            array( $this, &#039;settings_page_html&#039; ),    \/\/ Function to render the page\n            &#039;dashicons-megaphone&#039;,                   \/\/ Icon\n            60                                       \/\/ Position in menu\n        );\n    }\n\n\/\/ ... (rest of class) ...<\/code><\/pre>\n<p data-sourcepos=\"130:1-130:165\">This code adds a new top-level menu item called &#8220;Custom CTAs&#8221; to your WordPress admin sidebar. Clicking it will load the content generated by <code>settings_page_html()<\/code>.<\/p>\n<p data-sourcepos=\"132:1-132:40\"><strong>Step 2.2: Implement the Settings API<\/strong><\/p>\n<p data-sourcepos=\"134:1-134:133\">The WordPress Settings API is the standard way to handle plugin options. It manages saving, retrieving, and sanitizing your settings.<\/p>\n<p data-sourcepos=\"134:1-134:133\"><pre id=\"code-snippet-source-75\" class=\"code-snippet-source linkable-line-numbers\"><code class=\"language-php line-numbers\">\/\/ ... (inside My_Custom_CTA class) ...\n\n    \/**\n     * Register plugin settings\n     *\/\n    public function register_settings() {\n        register_setting(\n            &#039;my_custom_cta_group&#039;,   \/\/ Option group\n            $this-&gt;option_name,      \/\/ Option name (my_custom_ctas)\n            array( $this, &#039;sanitize_ctas_data&#039; ) \/\/ Sanitization callback\n        );\n    }\n\n    \/**\n     * Sanitize and validate CTA data before saving\n     *\/\n    public function sanitize_ctas_data( $input ) {\n        $clean_ctas = array();\n        if ( ! empty( $input ) &amp;&amp; is_array( $input ) ) {\n            foreach ( $input as $id =&gt; $cta ) {\n                $clean_cta = array();\n                $clean_cta[&#039;name&#039;]            = sanitize_text_field( $cta[&#039;name&#039;] ?? &#039;&#039; );\n                $clean_cta[&#039;image_url&#039;]       = esc_url_raw( $cta[&#039;image_url&#039;] ?? &#039;&#039; );\n                $clean_cta[&#039;title&#039;]           = sanitize_text_field( $cta[&#039;title&#039;] ?? &#039;&#039; );\n                $clean_cta[&#039;subtitle&#039;]        = sanitize_text_field( $cta[&#039;subtitle&#039;] ?? &#039;&#039; );\n                $clean_cta[&#039;paragraph&#039;]       = wp_kses_post( $cta[&#039;paragraph&#039;] ?? &#039;&#039; ); \/\/ Allow basic HTML\n                $clean_cta[&#039;button_label&#039;]    = sanitize_text_field( $cta[&#039;button_label&#039;] ?? &#039;&#039; );\n                $clean_cta[&#039;button_link&#039;]     = esc_url_raw( $cta[&#039;button_link&#039;] ?? &#039;&#039; );\n                $clean_cta[&#039;button_bg_color&#039;] = sanitize_hex_color( $cta[&#039;button_bg_color&#039;] ?? &#039;&#039; );\n                $clean_cta[&#039;button_text_color&#039;] = sanitize_hex_color( $cta[&#039;button_text_color&#039;] ?? &#039;&#039; );\n                $clean_ctas[ sanitize_key( $id ) ] = $clean_cta;\n            }\n        }\n        return $clean_ctas;\n    }\n\n\/\/ ... (rest of class) ...<\/code><\/pre>\n<ul data-sourcepos=\"176:1-178:0\">\n<li data-sourcepos=\"176:1-176:202\"><code><span class=\"citation-24\">register_setting()<\/span><\/code><span class=\"citation-24\">: This tells WordPress about our option group (<\/span><code><span class=\"citation-24\">my_custom_cta_group<\/span><\/code><span class=\"citation-24\">) and the option name (<\/span><code><span class=\"citation-24\">my_custom_ctas<\/span><\/code><span class=\"citation-24 citation-end-24\">) where all our CTA data will be stored as a single array.<\/span>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<li data-sourcepos=\"177:1-178:0\"><code>sanitize_ctas_data()<\/code>: This is a <strong>crucial security step<\/strong>. Before any data is saved to the database, it passes through this function. We use WordPress&#8217;s built-in sanitization functions (<code>sanitize_text_field<\/code>, <code>esc_url_raw<\/code>, <code>wp_kses_post<\/code>, <code>sanitize_hex_color<\/code>) to ensure only clean, safe data is stored.<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/d58358e5da11\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/d8d55174c08b\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/a53abf72415d\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/cd8e76c78b51\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/206ea64e587d\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/014e988045c9\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/0382c7f6638d\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/91fa6df44113\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/51f04dd92323\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/a635093b9808\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/fa7909f5a3f2\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"alignnone wp-image-8010 size-full\" title=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 12 58 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzEyXzU4X0FNLmpwZw\/a58b21916c8e\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 12 58 AM\" width=\"1860\" height=\"929\" \/><\/p>\n<p data-sourcepos=\"179:1-179:41\"><strong>Step 2.3: Building Dynamic CTA Fields<\/strong><\/p>\n<p data-sourcepos=\"181:1-181:97\">Now for the HTML of our settings page. We&#8217;ll create a main container and a template for new CTAs.<\/p>\n<p data-sourcepos=\"181:1-181:97\"><pre id=\"code-snippet-source-76\" class=\"code-snippet-source linkable-line-numbers\"><code class=\"language-php line-numbers\">\/\/ ... (inside My_Custom_CTA class) ...\n\n    \/**\n     * Settings page HTML\n     *\/\n    public function settings_page_html() {\n        ?&gt;\n        &lt;div class=&quot;wrap&quot;&gt;\n            &lt;h1&gt;&lt;?php _e( &#039;My Custom Call-to-Action Settings&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/h1&gt;\n\n            &lt;?php settings_errors(); \/\/ Displays messages from settings API ?&gt;\n\n            &lt;form method=&quot;post&quot; action=&quot;options.php&quot; class=&quot;my-custom-cta-form&quot;&gt;\n                &lt;?php settings_fields( &#039;my_custom_cta_group&#039; ); \/\/ Security fields ?&gt;\n                &lt;?php do_settings_sections( &#039;my_custom_cta_group&#039; ); \/\/ Not strictly needed here, but good practice ?&gt;\n\n                &lt;div id=&quot;cta-container&quot;&gt;\n                    &lt;?php\n                    \/\/ Load existing CTAs and render their fields\n                    $ctas = get_option( $this-&gt;option_name, array() );\n                    if ( ! empty( $ctas ) ) {\n                        foreach ( $ctas as $id =&gt; $cta ) {\n                            $this-&gt;render_cta_fields( $id, $cta );\n                        }\n                    }\n                    ?&gt;\n                &lt;\/div&gt;\n\n                &lt;p&gt;\n                    &lt;button type=&quot;button&quot; id=&quot;add-new-cta&quot; class=&quot;button button-primary&quot;&gt;\n                        &lt;?php _e( &#039;Add New CTA&#039;, &#039;my-custom-cta&#039; ); ?&gt;\n                    &lt;\/button&gt;\n                &lt;\/p&gt;\n\n                &lt;?php submit_button( __( &#039;Save All CTAs&#039;, &#039;my-custom-cta&#039; ) ); ?&gt;\n            &lt;\/form&gt;\n\n            &lt;div id=&quot;cta-template&quot; style=&quot;display: none;&quot;&gt;\n                &lt;?php $this-&gt;render_cta_fields( &#039;NEW_ID&#039;, array() ); \/\/ Template for new CTAs ?&gt;\n            &lt;\/div&gt;\n        &lt;\/div&gt;\n        &lt;?php\n    }\n\n    \/**\n     * Render individual CTA fields (private helper method)\n     * This function is called for each existing CTA and for the new CTA template.\n     *\/\n    private function render_cta_fields( $id, $cta_data ) {\n        \/\/ Retrieve data for the current CTA or set empty defaults for a new one\n        $cta_name          = $cta_data[&#039;name&#039;] ?? &#039;&#039;;\n        $image_url         = $cta_data[&#039;image_url&#039;] ?? &#039;&#039;;\n        $title             = $cta_data[&#039;title&#039;] ?? &#039;&#039;;\n        $subtitle          = $cta_data[&#039;subtitle&#039;] ?? &#039;&#039;;\n        $paragraph         = $cta_data[&#039;paragraph&#039;] ?? &#039;&#039;;\n        $button_label      = $cta_data[&#039;button_label&#039;] ?? &#039;&#039;;\n        $button_link       = $cta_data[&#039;button_link&#039;] ?? &#039;&#039;;\n        $button_bg_color   = $cta_data[&#039;button_bg_color&#039;] ?? &#039;&#039;;\n        $button_text_color = $cta_data[&#039;button_text_color&#039;] ?? &#039;&#039;;\n\n        $is_new = ( $id === &#039;NEW_ID&#039; ); \/\/ Check if this is the template for a new CTA\n        $display_id = $is_new ? &#039;&#039; : $id; \/\/ Don&#039;t show ID for template\n\n        ?&gt;\n        &lt;div class=&quot;cta-block&quot; data-id=&quot;&lt;?php echo esc_attr( $id ); ?&gt;&quot;&gt;\n            &lt;span class=&quot;cta-toggle dashicons dashicons-arrow-down&quot;&gt;&lt;\/span&gt;\n            &lt;h3&gt;\n                &lt;?php _e( &#039;CTA:&#039;, &#039;my-custom-cta&#039; ); ?&gt; &lt;span class=&quot;cta-block-name&quot;&gt;&lt;?php echo esc_html( $cta_name ?: &#039;(Untitled CTA)&#039; ); ?&gt;&lt;\/span&gt;\n                &lt;span class=&quot;cta-shortcode-display&quot; &lt;?php echo $is_new ? &#039;style=&quot;display:none;&quot;&#039; : &#039;&#039;; ?&gt;&gt;\n                    &lt;?php _e( &#039;Shortcode:&#039;, &#039;my-custom-cta&#039; ); ?&gt; &lt;code&gt;[my_custom_cta id=&quot;&lt;?php echo esc_attr( $display_id ); ?&gt;&quot;]&lt;\/code&gt;\n                &lt;\/span&gt;\n                &lt;button type=&quot;button&quot; class=&quot;button button-secondary delete-cta&quot; title=&quot;&lt;?php esc_attr_e( &#039;Delete this CTA&#039;, &#039;my-custom-cta&#039; ); ?&gt;&quot;&gt;&lt;span class=&quot;dashicons dashicons-trash&quot;&gt;&lt;\/span&gt;&lt;\/button&gt;\n            &lt;\/h3&gt;\n\n            &lt;div class=&quot;cta-content&quot; &lt;?php echo $is_new ? &#039;&#039; : &#039;style=&quot;display:none;&quot;&#039;; ?&gt;&gt;\n                &lt;table class=&quot;form-table&quot;&gt;\n                    &lt;tbody&gt;\n                        &lt;tr&gt;\n                            &lt;th scope=&quot;row&quot;&gt;&lt;label for=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][name]&#039; ); ?&gt;&quot;&gt;&lt;?php _e( &#039;CTA Internal Name (for identification):&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/label&gt;&lt;\/th&gt;\n                            &lt;td&gt;\n                                &lt;input type=&quot;text&quot;\n                                       name=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][name]&#039; ); ?&gt;&quot;\n                                       id=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][name]&#039; ); ?&gt;&quot;\n                                       value=&quot;&lt;?php echo esc_attr( $cta_name ); ?&gt;&quot;\n                                       class=&quot;regular-text cta-name-input&quot;\n                                       placeholder=&quot;&lt;?php esc_attr_e( &#039;e.g., Homepage Banner CTA&#039;, &#039;my-custom-cta&#039; ); ?&gt;&quot;\n                                       required&gt;\n                                &lt;p class=&quot;description&quot;&gt;&lt;?php _e( &#039;This name helps you identify the CTA in the <a href=\"https:\/\/danielepais.com\/journal\/understanding-the-role-of-back-end-development-in-web-applications\/\">backend<\/a>. It also forms part of the shortcode ID.&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/p&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th scope=&quot;row&quot;&gt;&lt;label for=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][image_url]&#039; ); ?&gt;&quot;&gt;&lt;?php _e( &#039;Image for CTA:&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/label&gt;&lt;\/th&gt;\n                            &lt;td&gt;\n                                &lt;div class=&quot;my-custom-cta-image-preview&quot;&gt;\n                                    &lt;?php if ( $image_url ) : ?&gt;\n                                        &lt;img src=&quot;&lt;?php echo esc_url( $image_url ); ?&gt;&quot; style=&quot;max-width:200px; height:auto;&quot;\/&gt;\n                                    &lt;?php endif; ?&gt;\n                                &lt;\/div&gt;\n                                &lt;input type=&quot;hidden&quot;\n                                       name=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][image_url]&#039; ); ?&gt;&quot;\n                                       id=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][image_url]&#039; ); ?&gt;&quot;\n                                       class=&quot;regular-text cta-image-url&quot;\n                                       value=&quot;&lt;?php echo esc_attr( $image_url ); ?&gt;&quot;&gt;\n                                &lt;button type=&quot;button&quot; class=&quot;button button-secondary upload-image-button&quot;&gt;\n                                    &lt;?php _e( &#039;Select Image&#039;, &#039;my-custom-cta&#039; ); ?&gt;\n                                &lt;\/button&gt;\n                                &lt;?php if ( $image_url ) : \/\/ Show remove button only if image exists ?&gt;\n                                    &lt;button type=&quot;button&quot; class=&quot;button button-secondary remove-image-button&quot;&gt;\n                                        &lt;?php _e( &#039;Remove Image&#039;, &#039;my-custom-cta&#039; ); ?&gt;\n                                    &lt;\/button&gt;\n                                &lt;?php endif; ?&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th scope=&quot;row&quot;&gt;&lt;label for=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][title]&#039; ); ?&gt;&quot;&gt;&lt;?php _e( &#039;Title (H3):&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/label&gt;&lt;\/th&gt;\n                            &lt;td&gt;\n                                &lt;input type=&quot;text&quot;\n                                       name=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][title]&#039; ); ?&gt;&quot;\n                                       id=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][title]&#039; ); ?&gt;&quot;\n                                       value=&quot;&lt;?php echo esc_attr( $title ); ?&gt;&quot;\n                                       class=&quot;regular-text&quot;\n                                       placeholder=&quot;&lt;?php esc_attr_e( &#039;e.g., Discover Our New Product&#039;, &#039;my-custom-cta&#039; ); ?&gt;&quot;&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th scope=&quot;row&quot;&gt;&lt;label for=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][subtitle]&#039; ); ?&gt;&quot;&gt;&lt;?php _e( &#039;Subtitle:&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/label&gt;&lt;\/th&gt;\n                            &lt;td&gt;\n                                &lt;input type=&quot;text&quot;\n                                       name=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][subtitle]&#039; ); ?&gt;&quot;\n                                       id=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][subtitle]&#039; ); ?&gt;&quot;\n                                       value=&quot;&lt;?php echo esc_attr( $subtitle ); ?&gt;&quot;\n                                       class=&quot;regular-text&quot;\n                                       placeholder=&quot;&lt;?php esc_attr_e( &#039;e.g., Limited Time Offer!&#039;, &#039;my-custom-cta&#039; ); ?&gt;&quot;&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th scope=&quot;row&quot;&gt;&lt;label for=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][paragraph]&#039; ); ?&gt;&quot;&gt;&lt;?php _e( &#039;Paragraph of Text:&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/label&gt;&lt;\/th&gt;\n                            &lt;td&gt;\n                                &lt;textarea name=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][paragraph]&#039; ); ?&gt;&quot;\n                                          id=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][paragraph]&#039; ); ?&gt;&quot;\n                                          rows=&quot;5&quot;\n                                          class=&quot;large-text&quot;&gt;&lt;?php echo esc_textarea( $paragraph ); ?&gt;&lt;\/textarea&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th scope=&quot;row&quot;&gt;&lt;label for=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_label]&#039; ); ?&gt;&quot;&gt;&lt;?php _e( &#039;Button Label:&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/label&gt;&lt;\/th&gt;\n                            &lt;td&gt;\n                                &lt;input type=&quot;text&quot;\n                                       name=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_label]&#039; ); ?&gt;&quot;\n                                       id=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_label]&#039; ); ?&gt;&quot;\n                                       value=&quot;&lt;?php echo esc_attr( $button_label ); ?&gt;&quot;\n                                       class=&quot;regular-text&quot;\n                                       placeholder=&quot;&lt;?php esc_attr_e( &#039;e.g., Learn More&#039;, &#039;my-custom-cta&#039; ); ?&gt;&quot;&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th scope=&quot;row&quot;&gt;&lt;label for=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_link]&#039; ); ?&gt;&quot;&gt;&lt;?php _e( &#039;Button Link (URL):&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/label&gt;&lt;\/th&gt;\n                            &lt;td&gt;\n                                &lt;input type=&quot;url&quot;\n                                       name=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_link]&#039; ); ?&gt;&quot;\n                                       id=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_link]&#039; ); ?&gt;&quot;\n                                       value=&quot;&lt;?php echo esc_attr( $button_link ); ?&gt;&quot;\n                                       class=&quot;regular-text&quot;\n                                       placeholder=&quot;&lt;?php esc_attr_e( &#039;e.g., https:\/\/yourwebsite.com\/page&#039;, &#039;my-custom-cta&#039; ); ?&gt;&quot;&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th scope=&quot;row&quot;&gt;&lt;label for=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_bg_color]&#039; ); ?&gt;&quot;&gt;&lt;?php _e( &#039;Button Background Color:&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/label&gt;&lt;\/th&gt;\n                            &lt;td&gt;\n                                &lt;input type=&quot;text&quot;\n                                       name=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_bg_color]&#039; ); ?&gt;&quot;\n                                       id=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_bg_color]&#039; ); ?&gt;&quot;\n                                       value=&quot;&lt;?php echo esc_attr( $button_bg_color ); ?&gt;&quot;\n                                       class=&quot;my-custom-cta-color-field&quot;\n                                       data-default-color=&quot;#0073aa&quot;&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                        &lt;tr&gt;\n                            &lt;th scope=&quot;row&quot;&gt;&lt;label for=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_text_color]&#039; ); ?&gt;&quot;&gt;&lt;?php _e( &#039;Button Text Color:&#039;, &#039;my-custom-cta&#039; ); ?&gt;&lt;\/label&gt;&lt;\/th&gt;\n                            &lt;td&gt;\n                                &lt;input type=&quot;text&quot;\n                                       name=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_text_color]&#039; ); ?&gt;&quot;\n                                       id=&quot;&lt;?php echo esc_attr( $this-&gt;option_name . &#039;[&#039; . $id . &#039;][button_text_color]&#039; ); ?&gt;&quot;\n                                       value=&quot;&lt;?php echo esc_attr( $button_text_color ); ?&gt;&quot;\n                                       class=&quot;my-custom-cta-color-field&quot;\n                                       data-default-color=&quot;#ffffff&quot;&gt;\n                            &lt;\/td&gt;\n                        &lt;\/tr&gt;\n                    &lt;\/tbody&gt;\n                &lt;\/table&gt;\n            &lt;\/div&gt;\n        &lt;\/div&gt;\n        &lt;?php\n    }<\/code><\/pre>\n<p data-sourcepos=\"380:1-380:271\">The <code>settings_page_html()<\/code> function generates the main admin page. It loops through any existing CTAs and calls <code>render_cta_fields()<\/code> for each. It also includes an &#8220;Add New CTA&#8221; button and a hidden <code>cta-template<\/code> that will be cloned by JavaScript when a new CTA is added.<\/p>\n<p data-sourcepos=\"382:1-382:250\">The <code>render_cta_fields()<\/code> function is the workhorse. It outputs the HTML for each individual CTA block, including all the input fields. <strong>Notice the <code>my-custom-cta-color-field<\/code> class on our color inputs \u2013 this is key for the WordPress color picker!<\/strong><\/p>\n<p data-sourcepos=\"382:1-382:250\"><img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/2dc18adaf688\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/c9f317338d33\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/5970ffd19d5f\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/7f32181df402\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/f67481e53362\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/c6f69633fe38\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/39eafb27b339\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/71f22bc95e4e\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/255a9be4a899\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/d93bead65ef2\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/464faa1256ba\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"alignnone wp-image-8013 size-full\" title=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 03 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE3X0FNLmpwZw\/dfb4ac4929a0\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 17 AM\" width=\"1700\" height=\"1422\" \/><\/p>\n<hr data-sourcepos=\"384:1-384:3\" \/>\n<h2 data-sourcepos=\"386:1-386:43\"><span class=\"ez-toc-section\" id=\"Section_3_Enqueuing_Styles_and_Scripts\"><\/span>Section 3: Enqueuing Styles and Scripts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p data-sourcepos=\"388:1-388:138\">For our admin interface to look good and be interactive, and for our frontend CTAs to be styled, we need to load CSS and JavaScript files.<\/p>\n<p data-sourcepos=\"390:1-390:57\"><strong>Step 3.1: Admin-Side Assets (<code>enqueue_admin_scripts<\/code>)<\/strong><\/p>\n<p data-sourcepos=\"392:1-392:50\">Add this method inside your <code>My_Custom_CTA<\/code> class:<\/p>\n<p data-sourcepos=\"392:1-392:50\"><pre id=\"code-snippet-source-77\" class=\"code-snippet-source linkable-line-numbers\"><code class=\"language-php line-numbers\">\/\/ ... (inside My_Custom_CTA class) ...\n\n    \/**\n     * Enqueue admin scripts and styles\n     *\/\n    public function enqueue_admin_scripts( $hook ) {\n        \/\/ Only load scripts\/styles on our specific admin page\n        if ( &#039;toplevel_page_my-custom-cta&#039; != $hook ) {\n            return;\n        }\n\n        \/\/ Enqueue media uploader scripts (for image uploads)\n        wp_enqueue_media();\n\n        \/\/ Enqueue WordPress color picker scripts and styles\n        wp_enqueue_style( &#039;wp-color-picker&#039; );\n        wp_enqueue_script( &#039;wp-color-picker&#039; );\n\n        \/\/ Enqueue our custom admin styles\n        wp_enqueue_style( &#039;my-custom-cta-admin-style&#039;, plugin_dir_url( __FILE__ ) . &#039;css\/admin-style.css&#039;, array( &#039;wp-color-picker&#039; ) );\n\n        \/\/ Enqueue our custom admin JavaScript\n        wp_enqueue_script(\n            &#039;my-custom-cta-admin-script&#039;,\n            plugin_dir_url( __FILE__ ) . &#039;js\/admin-script.js&#039;,\n            array( &#039;jquery&#039;, &#039;wp-mediaelement&#039;, &#039;wp-color-picker&#039; ), \/\/ Dependencies\n            null, \/\/ Version\n            true  \/\/ In footer\n        );\n\n        \/\/ Pass PHP data to our JavaScript file\n        wp_localize_script(\n            &#039;my-custom-cta-admin-script&#039;,\n            &#039;myCustomCtaAdmin&#039;,\n            array(\n                &#039;ajax_url&#039;      =&gt; admin_url( &#039;admin-ajax.php&#039; ),\n                &#039;nonce&#039;         =&gt; wp_create_nonce( &#039;my-custom-cta-nonce&#039; ),\n                &#039;media_title&#039;   =&gt; __( &#039;Select CTA Image&#039;, &#039;my-custom-cta&#039; ),\n                &#039;media_button&#039;  =&gt; __( &#039;Use This Image&#039;, &#039;my-custom-cta&#039; ),\n            )\n        );\n    }\n\n\/\/ ... (rest of class) ...<\/code><\/pre>\n<p data-sourcepos=\"441:1-441:33\">This method is crucial. It loads:<\/p>\n<ul data-sourcepos=\"442:1-446:0\">\n<li data-sourcepos=\"442:1-442:115\"><code><span class=\"citation-23\">wp_enqueue_media()<\/span><\/code><span class=\"citation-23 citation-end-23\">: Necessary for the &#8220;Select Image&#8221; button to open the WordPress media library.<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/7a71ee67a4b3\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/885e029da046\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/76d1e8afeef7\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/446472b7e7ca\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/6ed857ca34ec\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/8658bbbbf4d9\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/4c4385ca6e15\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/44052d5ad032\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/45599e85f318\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/99791e267c3b\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/0feec754e532\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"alignnone wp-image-8014 size-full\" title=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 17 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzE5X0FNLmpwZw\/e8842f71c749\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 19 AM\" width=\"1108\" height=\"317\" \/> <\/span><\/p>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<li data-sourcepos=\"443:1-443:180\"><code><span class=\"citation-22\">wp-color-picker<\/span><\/code><span class=\"citation-22 citation-end-22\">: This is WordPress&#8217;s built-in color picker.<\/span> By enqueuing its assets, we can instantly turn our color input fields into interactive color pickers.<br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/bd8019ca5fee\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/8f4a2e7eeff2\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/c1295615d1ed\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/51b2e02b4360\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/dd3fbb6d1ebd\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/9fa59525d7b4\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/b9959fec537b\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/a98c03de7186\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/300ca7203413\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/477abd18b540\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/991a2394d18c\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"alignnone wp-image-8015 size-full\" title=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 22 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzIyX0FNLmpwZw\/595d920b7363\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 22 AM\" width=\"910\" height=\"322\" \/><\/p>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<li data-sourcepos=\"444:1-444:53\">Our custom <code>admin-style.css<\/code> and <code>admin-script.js<\/code>.<\/li>\n<li data-sourcepos=\"445:1-446:0\"><code><span class=\"citation-21\">wp_localize_script()<\/span><\/code><span class=\"citation-21 citation-end-21\">: A handy function to pass small bits of dynamic PHP data (like text strings or nonces) to your JavaScript.<\/span><\/li>\n<\/ul>\n<p data-sourcepos=\"447:1-447:62\"><strong>Step 3.2: Frontend-Side Assets (<code>enqueue_frontend_styles<\/code>)<\/strong><\/p>\n<p data-sourcepos=\"449:1-449:50\">Add this method inside your <code>My_Custom_CTA<\/code> class:<\/p>\n<p data-sourcepos=\"449:1-449:50\"><pre id=\"code-snippet-source-78\" class=\"code-snippet-source linkable-line-numbers\"><code class=\"language-php line-numbers\">\/\/ ... (inside My_Custom_CTA class) ...\n\n    \/**\n     * Enqueue frontend styles\n     *\/\n    public function enqueue_frontend_styles() {\n        wp_enqueue_style( &#039;my-custom-cta-frontend-style&#039;, plugin_dir_url( __FILE__ ) . &#039;css\/frontend-style.css&#039; );\n    }\n\n\/\/ ... (rest of class) ...<\/code><\/pre>\n<p data-sourcepos=\"464:1-464:160\">This simple function ensures that the <code>frontend-style.css<\/code> file is loaded on the public-facing side of your website, applying all the visual magic to your CTAs.<\/p>\n<hr data-sourcepos=\"466:1-466:3\" \/>\n<h3 data-sourcepos=\"468:1-468:59\"><span class=\"ez-toc-section\" id=\"Section_4_The_Activation_Hook_%E2%80%93_Auto-Generating_Assets\"><\/span>Section 4: The Activation Hook &#8211; Auto-Generating Assets<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p data-sourcepos=\"470:1-470:283\">This is where the magic of &#8220;single PHP file&#8221; managing separate CSS\/JS files happens. When you activate your plugin, this special function will create the <code>css<\/code> and <code>js<\/code> folders, and populate the <code>admin-style.css<\/code>, <code>frontend-style.css<\/code>, and <code>admin-script.js<\/code> files with their content.<\/p>\n<p data-sourcepos=\"472:1-472:267\"><strong>Important Note:<\/strong> If you make changes to the CSS or JavaScript code <em>within<\/em> your <code>my-custom-cta.php<\/code> file, you will need to <strong>Deactivate and then Reactivate<\/strong> your plugin from the WordPress Plugins page for those changes to be written to the external CSS\/JS files.<\/p>\n<p data-sourcepos=\"474:1-474:115\">Add the following code <strong>outside<\/strong> your <code>My_Custom_CTA<\/code> class, at the very bottom of your <code>my-custom-cta.php<\/code> file:<\/p>\n<p data-sourcepos=\"474:1-474:115\"><pre id=\"code-snippet-source-79\" class=\"code-snippet-source linkable-line-numbers\"><code class=\"language-php line-numbers\">\/\/ ... (End of My_Custom_CTA class and its initialization) ...\n\n\/\/ Create necessary folders and files on plugin activation and update their content\nregister_activation_hook( __FILE__, &#039;my_custom_cta_activate&#039; );\n\nfunction my_custom_cta_activate() {\n    $plugin_dir = plugin_dir_path( __FILE__ );\n    $css_dir    = $plugin_dir . &#039;css\/&#039;;\n    $js_dir     = $plugin_dir . &#039;js\/&#039;;\n\n    \/\/ Create CSS directory if it doesn&#039;t exist\n    if ( ! file_exists( $css_dir ) ) {\n        wp_mkdir_p( $css_dir );\n    }\n\n    \/\/ Create JS directory if it doesn&#039;t exist\n    if ( ! file_exists( $js_dir ) ) {\n        wp_mkdir_p( $js_dir );\n    }\n\n    \/\/ Always update admin-style.css with the latest content\n    $admin_css_file = $css_dir . &#039;admin-style.css&#039;;\n    file_put_contents( $admin_css_file,\n        &#039;.cta-block {\n            background: #fff;\n            border: 1px solid #c3c4c7;\n            margin-bottom: 15px;\n            padding: 10px 20px;\n            position: relative;\n        }\n        .cta-block h3 {\n            margin: 0;\n            padding-right: 100px; \/* Space for delete button *\/\n            position: relative;\n        }\n        .cta-block h3 .cta-toggle {\n            cursor: pointer;\n            float: left;\n            margin-right: 10px;\n            font-size: 20px;\n            line-height: 1;\n            width: 20px;\n            height: 20px;\n            text-align: center;\n            vertical-align: middle;\n            margin-top: 2px;\n        }\n        .cta-block h3 .cta-toggle.dashicons-arrow-down:before {\n            content: &quot;\\\\f140&quot;; \/* down arrow *\/\n        }\n        .cta-block h3 .cta-toggle.dashicons-arrow-up:before {\n            content: &quot;\\\\f142&quot;; \/* up arrow *\/\n        }\n        .cta-block .delete-cta {\n            position: absolute;\n            right: 0;\n            top: 0;\n            color: #a00;\n            border: none;\n            background: none;\n            box-shadow: none;\n            cursor: pointer;\n        }\n        .cta-block .delete-cta:hover {\n            color: #dc3232;\n        }\n        .my-custom-cta-image-preview img {\n            border: 1px solid #ddd;\n            padding: 5px;\n            background: #f9f9f9;\n            margin-bottom: 10px;\n            display: block;\n        }\n        .cta-shortcode-display {\n            font-size: 0.9em;\n            color: #555;\n            margin-left: 15px;\n        }\n        .cta-shortcode-display code {\n            background: #f0f0f0;\n            padding: 2px 5px;\n            border-radius: 3px;\n            border: 1px solid #e0e0e0;\n        }\n        #add-new-cta {\n            margin-top: 20px;\n        }\n        \/* Styling for color picker *\/\n        .wp-picker-container {\n            display: inline-block; \/* Adjust if necessary *\/\n            vertical-align: middle;\n        }\n        .my-custom-cta-color-field {\n            width: 80px !important; \/* Make color input smaller *\/\n        }&#039;\n    );\n\n    \/\/ Always update frontend-style.css with the latest content\n    $frontend_css_file = $css_dir . &#039;frontend-style.css&#039;;\n    file_put_contents( $frontend_css_file,\n        &#039;.my-custom-cta-block {\n            border: 1px solid #eee;\n            padding: 20px;\n            margin-bottom: 20px;\n            display: flex;\n            flex-wrap: wrap;\n            align-items: center;\n            background: #f9f9f9;\n            box-shadow: 0 4px 10px rgba(0,0,0,0.08); \/* More prominent subtle shadow *\/\n            border-radius: 8px; \/* Slightly rounded corners for the block *\/\n            overflow: hidden; \/* Important for border-radius on nested elements *\/\n            transition: transform 0.3s ease, box-shadow 0.3s ease; \/* Smooth transition for hover effects on the block itself *\/\n        }\n        .my-custom-cta-block:hover {\n            transform: translateY(-3px); \/* Subtle lift effect on hover *\/\n            box-shadow: 0 6px 15px rgba(0,0,0,0.12); \/* Increase shadow on hover *\/\n        }\n        .my-custom-cta-image {\n            flex: 0 0 30%; \/* Take 30% width *\/\n            max-width: 30%;\n            margin-right: 20px;\n            \/* No padding here as the frame will provide it *\/\n        }\n        .my-custom-cta-image img {\n            max-width: 100%;\n            height: auto;\n            display: block;\n            border-radius: 4px; \/* Slightly rounded corners for the image itself *\/\n            \/* Enhanced Shadow and Frame *\/\n            border: 6px solid #fff; \/* A white frame *\/\n            padding: 3px; \/* Small inner padding for the frame effect *\/\n            background-color: #fff; \/* Ensure background is white if border is transparent *\/\n            box-shadow: 0 10px 30px rgba(0,0,0,0.3), 0 0 0 1px rgba(0,0,0,0.05) inset; \/* Enhanced shadow + subtle inner line *\/\n            transition: transform 0.3s ease, box-shadow 0.3s ease; \/* Smooth transition for image hover *\/\n        }\n        .my-custom-cta-block:hover .my-custom-cta-image img {\n            transform: scale(1.02); \/* Slightly zoom image on block hover *\/\n            box-shadow: 0 15px 40px rgba(0,0,0,0.4), 0 0 0 1px rgba(0,0,0,0.08) inset; \/* Even stronger shadow on hover *\/\n        }\n        .my-custom-cta-content {\n            flex: 1; \/* Take remaining width *\/\n        }\n        .my-custom-cta-title {\n            font-size: 1.8em;\n            margin-top: 0;\n            margin-bottom: 10px;\n            color: #333;\n            line-height: 1.2; \/* Improve readability *\/\n        }\n        .my-custom-cta-subtitle {\n            font-size: 1.2em;\n            margin-bottom: 10px;\n            color: #666;\n            font-weight: 400; \/* Ensure subtitle is not too bold *\/\n        }\n        .my-custom-cta-paragraph {\n            margin-bottom: 15px;\n            line-height: 1.6;\n            color: #444;\n        }\n        .my-custom-cta-button .button {\n            border: none; \/* Make sure default border is removed if inline color is applied *\/\n            padding: 12px 25px; \/* Slightly larger padding *\/\n            border-radius: 5px;\n            text-decoration: none;\n            transition: all 0.3s ease; \/* Smooth transition for hover effects *\/\n            cursor: pointer;\n            display: inline-block; \/* Ensure it behaves like a block for padding\/margins *\/\n            font-weight: 600; \/* Make button text a bit bolder *\/\n            letter-spacing: 0.5px; \/* Add slight letter spacing *\/\n            box-shadow: 0 2px 5px rgba(0,0,0,0.1); \/* Subtle shadow on button *\/\n        }\n        .my-custom-cta-button .button:hover {\n            filter: brightness(1.15); \/* Make it brighter on hover *\/\n            transform: translateY(-1px); \/* Slight lift for the button itself *\/\n            box-shadow: 0 4px 8px rgba(0,0,0,0.15); \/* More prominent shadow on hover *\/\n        }\n        \/* Responsive adjustments *\/\n        @media (max-width: 768px) {\n            .my-custom-cta-block {\n                flex-direction: column;\n                text-align: center;\n                padding: 15px; \/* Adjust padding for smaller screens *\/\n            }\n            .my-custom-cta-image {\n                flex: none;\n                max-width: 80%; \/* Image takes more width on <a href=\"https:\/\/danielepais.com\/journal\/devlop-app-build-fullstack-mobile-apps-with-ai\/\">mobile<\/a> *\/\n                margin-right: 0;\n                margin-bottom: 20px;\n                order: -1; \/* Place image above text on mobile *\/\n            }\n            .my-custom-cta-image img {\n                width: 100%; \/* Ensure image fills its container *\/\n            }\n            .my-custom-cta-content {\n                width: 100%; \/* Content takes full width *\/\n            }\n        }&#039;\n    );\n\n    \/\/ Always update admin-script.js with the latest content\n    $admin_js_file = $js_dir . &#039;admin-script.js&#039;;\n    file_put_contents( $admin_js_file,\n        &#039;(function($) {\n            $(document).ready(function() {\n                var mediaUploader;\n\n                \/\/ Function to initialize color pickers\n                function initializeColorPickers() {\n                    if (typeof $.fn.wpColorPicker !== \\&#039;undefined\\&#039;) {\n                        $(\\&#039;.my-custom-cta-color-field\\&#039;).each(function() {\n                            if ($(this).data(\\&#039;wpColorPicker\\&#039;) !== undefined) {\n                                $(this).wpColorPicker(\\&#039;destroy\\&#039;);\n                            }\n                        });\n                        $(\\&#039;.my-custom-cta-color-field\\&#039;).wpColorPicker();\n                    }\n                }\n\n                \/\/ Initialize color pickers on page load\n                initializeColorPickers();\n\n                \/\/ Add new CTA block\n                $(\\&#039;#add-new-cta\\&#039;).on(\\&#039;click\\&#039;, function() {\n                    var template = $(\\&#039;#cta-template\\&#039;).html();\n                    var newId = \\&#039;cta-\\&#039; + Date.now();\n                    var newBlock = $(template.replace(\/NEW_ID\/g, newId));\n                    newBlock.find(\\&#039;.cta-name-input\\&#039;).attr(\\&#039;required\\&#039;, true);\n                    newBlock.find(\\&#039;.cta-shortcode-display\\&#039;).hide();\n                    $(\\&#039;#cta-container\\&#039;).append(newBlock);\n                    newBlock.find(\\&#039;.cta-content\\&#039;).show();\n                    newBlock.find(\\&#039;.cta-toggle\\&#039;).removeClass(\\&#039;dashicons-arrow-down\\&#039;).addClass(\\&#039;dashicons-arrow-up\\&#039;);\n\n                    \/\/ Re-initialize color pickers for the new block\n                    newBlock.find(\\&#039;.my-custom-cta-color-field\\&#039;).wpColorPicker();\n                });\n\n                \/\/ Toggle CTA block content\n                $(document).on(\\&#039;click\\&#039;, \\&#039;.cta-toggle, .cta-block h3\\&#039;, function(e) {\n                    if ($(e.target).is(\\&#039;.delete-cta\\&#039;) || $(e.target).closest(\\&#039;.delete-cta\\&#039;).length) {\n                        return;\n                    }\n                    var $block = $(this).closest(\\&#039;.cta-block\\&#039;);\n                    $block.find(\\&#039;.cta-content\\&#039;).slideToggle(200);\n                    $(this).toggleClass(\\&#039;dashicons-arrow-down dashicons-arrow-up\\&#039;);\n                });\n\n                \/\/ Delete CTA block\n                $(document).on(\\&#039;click\\&#039;, \\&#039;.delete-cta\\&#039;, function() {\n                    if (confirm(\\&#039;Are you sure you want to delete this CTA? This action cannot be undone.\\&#039;)) {\n                        $(this).closest(\\&#039;.cta-block\\&#039;).remove();\n                    }\n                });\n\n                \/\/ Update CTA name display\n                $(document).on(\\&#039;input\\&#039;, \\&#039;.cta-name-input\\&#039;, function() {\n                    var ctaName = $(this).val().trim();\n                    var $block = $(this).closest(\\&#039;.cta-block\\&#039;);\n                    var $nameDisplay = $block.find(\\&#039;.cta-block-name\\&#039;);\n                    if (ctaName) {\n                        $nameDisplay.text(ctaName);\n                    } else {\n                        $nameDisplay.text(\\&#039;(Untitled CTA)\\&#039;);\n                    }\n                });\n\n                \/\/ Media Uploader for image\n                $(document).on(\\&#039;click\\&#039;, \\&#039;.upload-image-button\\&#039;, function(e) {\n                    e.preventDefault();\n\n                    var $button = $(this);\n                    var $imageInput = $button.siblings(\\&#039;.cta-image-url\\&#039;);\n                    var $imagePreview = $button.siblings(\\&#039;.my-custom-cta-image-preview\\&#039;);\n\n                    if (mediaUploader) {\n                        mediaUploader.open();\n                        return;\n                    }\n\n                    mediaUploader = wp.media({\n                        title: myCustomCtaAdmin.media_title,\n                        button: {\n                            text: myCustomCtaAdmin.media_button\n                        },\n                        multiple: false\n                    });\n\n                    mediaUploader.on(\\&#039;select\\&#039;, function() {\n                        var attachment = mediaUploader.state().get(\\&#039;selection\\&#039;).first().toJSON();\n                        $imageInput.val(attachment.url);\n                        $imagePreview.html(\\&#039;&lt;img src=&quot;\\&#039; + attachment.url + \\&#039;&quot; style=&quot;max-width:200px; height:auto;&quot;\/&gt;\\&#039;);\n                        if ($button.siblings(\\&#039;.remove-image-button\\&#039;).length === 0) {\n                            $button.after(\\&#039;&lt;button type=&quot;button&quot; class=&quot;button button-secondary remove-image-button&quot;&gt;Remove Image&lt;\/button&gt;\\&#039;);\n                        }\n                    });\n\n                    mediaUploader.open();\n                });\n\n                \/\/ Remove image\n                $(document).on(\\&#039;click\\&#039;, \\&#039;.remove-image-button\\&#039;, function() {\n                    var $button = $(this);\n                    var $imageInput = $button.siblings(\\&#039;.cta-image-url\\&#039;);\n                    var $imagePreview = $button.siblings(\\&#039;.my-custom-cta-image-preview\\&#039;);\n\n                    $imageInput.val(\\&#039;\\&#039;);\n                    $imagePreview.html(\\&#039;\\&#039;);\n                    $button.remove();\n                });\n            });\n        })(jQuery);&#039;\n    );\n}<\/code><\/pre>\n<p data-sourcepos=\"792:1-792:284\">This section is perhaps the most unique part of our plugin. It dynamically creates and updates the <code>admin-style.css<\/code>, <code>frontend-style.css<\/code>, and <code>admin-script.js<\/code> files whenever the plugin is activated or reactivated. This means you only need to manage the code in <code>my-custom-cta.php<\/code>!<\/p>\n<hr data-sourcepos=\"794:1-794:3\" \/>\n<h2 data-sourcepos=\"796:1-796:51\"><span class=\"ez-toc-section\" id=\"Section_5_Displaying_Your_CTAs_with_Shortcodes\"><\/span>Section 5: Displaying Your CTAs with Shortcodes<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/1073f4e1f6a7\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/cad2f31d97e0\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/00e33a9679fe\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/726dc3006c0d\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/090c09e75778\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/e931e780f856\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/cb007609caa3\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/833037b509eb\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/0423ae123b51\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/f12cb6304daa\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/337bebb8dea7\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"alignnone wp-image-8012 size-full\" title=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 12 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9NeS1DdXN0b20tQ1RBcy3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzEyX0FNLmpwZw\/094ac2b2c1ce\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"My Custom CTAs \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 12 AM\" width=\"1636\" height=\"425\" \/><\/p>\n<p data-sourcepos=\"798:1-798:97\">Now that we can create and manage our CTAs, let&#8217;s learn how to display them anywhere on our site.<\/p>\n<p data-sourcepos=\"800:1-800:72\">Add the <code>render_cta_shortcode<\/code> method inside your <code>My_Custom_CTA<\/code> class:<\/p>\n<p data-sourcepos=\"800:1-800:72\"><pre id=\"code-snippet-source-80\" class=\"code-snippet-source linkable-line-numbers\"><code class=\"language-php line-numbers\">\/\/ ... (inside My_Custom_CTA class) ...\n\n    \/**\n     * Render CTA shortcode\n     * Usage: [my_custom_cta id=&quot;your_cta_id&quot;]\n     *\/\n    public function render_cta_shortcode( $atts ) {\n        \/\/ Parse shortcode attributes, setting &#039;id&#039; as default\n        $atts = shortcode_atts(\n            array(\n                &#039;id&#039; =&gt; &#039;&#039;,\n            ),\n            $atts,\n            &#039;my_custom_cta&#039;\n        );\n\n        $cta_id = sanitize_key( $atts[&#039;id&#039;] ); \/\/ Sanitize the provided ID\n        if ( empty( $cta_id ) ) {\n            return &#039;&lt;p style=&quot;color:red;&quot;&gt;&#039; . __( &#039;Error: CTA ID is missing in shortcode.&#039;, &#039;my-custom-cta&#039; ) . &#039;&lt;\/p&gt;&#039;;\n        }\n\n        \/\/ Retrieve all saved CTAs\n        $ctas = get_option( $this-&gt;option_name, array() );\n        \/\/ Get the specific CTA data by ID\n        $cta_data = $ctas[ $cta_id ] ?? null;\n\n        if ( ! $cta_data ) {\n            return &#039;&lt;p style=&quot;color:red;&quot;&gt;&#039; . sprintf( __( &#039;Error: CTA with ID &quot;%s&quot; not found.&#039;, &#039;my-custom-cta&#039; ), esc_html( $cta_id ) ) . &#039;&lt;\/p&gt;&#039;;\n        }\n\n        \/\/ Prepare inline styles for the button (from color pickers)\n        $button_styles = &#039;&#039;;\n        if ( ! empty( $cta_data[&#039;button_bg_color&#039;] ) ) {\n            $button_styles .= &#039;background-color:&#039; . esc_attr( $cta_data[&#039;button_bg_color&#039;] ) . &#039;;&#039;;\n        }\n        if ( ! empty( $cta_data[&#039;button_text_color&#039;] ) ) {\n            $button_styles .= &#039;color:&#039; . esc_attr( $cta_data[&#039;button_text_color&#039;] ) . &#039;;&#039;;\n        }\n        if ( ! empty( $button_styles ) ) {\n            $button_styles = rtrim($button_styles, &#039;;&#039;) . &#039; !important;&#039;; \/\/ Use !important for robustness\n        }\n\n        \/\/ Use output buffering to capture the HTML output\n        ob_start();\n        ?&gt;\n        &lt;div class=&quot;my-custom-cta-block&quot;&gt;\n            &lt;?php if ( ! empty( $cta_data[&#039;image_url&#039;] ) ) : ?&gt;\n                &lt;div class=&quot;my-custom-cta-image&quot;&gt;\n                    &lt;img src=&quot;&lt;?php echo esc_url( $cta_data[&#039;image_url&#039;] ); ?&gt;&quot; alt=&quot;&lt;?php echo esc_attr( $cta_data[&#039;title&#039;] ); ?&gt;&quot;&gt;\n                &lt;\/div&gt;\n            &lt;?php endif; ?&gt;\n\n            &lt;div class=&quot;my-custom-cta-content&quot;&gt;\n                &lt;?php if ( ! empty( $cta_data[&#039;title&#039;] ) ) : ?&gt;\n                    &lt;h3 class=&quot;my-custom-cta-title&quot;&gt;&lt;?php echo esc_html( $cta_data[&#039;title&#039;] ); ?&gt;&lt;\/h3&gt;\n                &lt;?php endif; ?&gt;\n\n                &lt;?php if ( ! empty( $cta_data[&#039;subtitle&#039;] ) ) : ?&gt;\n                    &lt;p class=&quot;my-custom-cta-subtitle&quot;&gt;&lt;?php echo esc_html( $cta_data[&#039;subtitle&#039;] ); ?&gt;&lt;\/p&gt;\n                &lt;?php endif; ?&gt;\n\n                &lt;?php if ( ! empty( $cta_data[&#039;paragraph&#039;] ) ) : ?&gt;\n                    &lt;div class=&quot;my-custom-cta-paragraph&quot;&gt;&lt;?php echo wp_kses_post( $cta_data[&#039;paragraph&#039;] ); ?&gt;&lt;\/div&gt;\n                &lt;?php endif; ?&gt;\n\n                &lt;?php if ( ! empty( $cta_data[&#039;button_label&#039;] ) &amp;&amp; ! empty( $cta_data[&#039;button_link&#039;] ) ) : ?&gt;\n                    &lt;div class=&quot;my-custom-cta-button&quot;&gt;\n                        &lt;a href=&quot;&lt;?php echo esc_url( $cta_data[&#039;button_link&#039;] ); ?&gt;&quot; class=&quot;button&quot; style=&quot;&lt;?php echo esc_attr( $button_styles ); ?&gt;&quot;&gt;&lt;?php echo esc_html( $cta_data[&#039;button_label&#039;] ); ?&gt;&lt;\/a&gt;\n                    &lt;\/div&gt;\n                &lt;?php endif; ?&gt;\n            &lt;\/div&gt;\n        &lt;\/div&gt;\n        &lt;?php\n        return ob_get_clean(); \/\/ Return the captured HTML\n    }<\/code><\/pre>\n<p data-sourcepos=\"880:1-880:67\">This method is called when WordPress encounters your shortcode. It:<\/p>\n<ul data-sourcepos=\"881:1-885:0\">\n<li data-sourcepos=\"881:1-881:55\">Retrieves the CTA <code>id<\/code> from the shortcode attributes.<\/li>\n<li data-sourcepos=\"882:1-882:61\">Fetches the corresponding CTA data from your saved options.<\/li>\n<li data-sourcepos=\"883:1-883:94\">Dynamically applies the chosen background and text colors to the button using inline styles.<\/li>\n<li data-sourcepos=\"884:1-885:0\">Outputs the full HTML structure for your CTA, complete with image, text, and button, applying all the classes we&#8217;ve prepared for styling.<\/li>\n<\/ul>\n<p data-sourcepos=\"886:1-886:38\"><strong>Step 5.2: How to Use the Shortcode<\/strong><\/p>\n<p data-sourcepos=\"888:1-888:101\">Once you&#8217;ve saved and activated your plugin, you can place your CTAs anywhere on your WordPress site.<\/p>\n<ol data-sourcepos=\"890:1-899:0\">\n<li data-sourcepos=\"890:1-890:55\">Go to <strong>Custom CTAs<\/strong> in your WordPress admin menu.<\/li>\n<li data-sourcepos=\"891:1-891:109\">Create a new CTA or edit an existing one. Give it a unique &#8220;CTA Internal Name&#8221; (e.g., &#8220;Homepage Banner&#8221;).<\/li>\n<li data-sourcepos=\"892:1-892:22\"><strong>Save All CTAs<\/strong>.<\/li>\n<li data-sourcepos=\"893:1-893:154\">After saving, you&#8217;ll see a shortcode displayed next to your CTA&#8217;s name: \u00a0(the ID will match your internal name).<\/li>\n<li data-sourcepos=\"894:1-894:24\">Copy this shortcode.<\/li>\n<li data-sourcepos=\"895:1-899:0\">Paste it into any:\n<ul data-sourcepos=\"896:5-899:0\">\n<li data-sourcepos=\"896:5-896:112\">WordPress post or page (using a &#8220;Shortcode&#8221; block in the Block Editor, or directly in the Classic Editor).<\/li>\n<li data-sourcepos=\"897:5-897:18\">Text Widget.<\/li>\n<li data-sourcepos=\"898:5-899:0\">Page builder module that accepts shortcodes.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/e5b6ddf9fbe8\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/e8ee20c729c6\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/b5b675f8e1aa\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/368250f8290d\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/feaee9188521\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/ed6fb3c2ae7c\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/b9f579ed4990\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/049420d26a17\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/fa1808013566\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/35c34a795b4f\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/2509e596d940\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"alignnone wp-image-8018 size-full\" title=\"Edit Post \u201ctest\u201d \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 29 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi9FZGl0LVBvc3QtdGVzdC3igLktUGh1a2V0LVdlYi1EZXNpZ24t4oCULVdvcmRQcmVzcy0wNi0xMS0yMDI1XzAxXzI5X0FNLmpwZw\/0c80191dd6b5\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"Edit Post \u201ctest\u201d \u2039 Phuket Web Design \u2014 WordPress 06 11 2025 01 29 AM\" width=\"1259\" height=\"694\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAIAAAAAAAP\/\/\/ywAAAAAAQABAAACAUwAOw==\" fifu-lazy=\"1\" fifu-data-sizes=\"auto\" fifu-data-srcset=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/33c0395e003d\/wordpress-custom-cta-plugin.webp?p=8001&w=75&h=0&c=0 75w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/e39441cbb827\/wordpress-custom-cta-plugin.webp?p=8001&w=100&h=0&c=0 100w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/25176164d2cd\/wordpress-custom-cta-plugin.webp?p=8001&w=150&h=0&c=0 150w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/34b8551675c4\/wordpress-custom-cta-plugin.webp?p=8001&w=240&h=0&c=0 240w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/28861c62f68a\/wordpress-custom-cta-plugin.webp?p=8001&w=320&h=0&c=0 320w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/ea0d5bd634bd\/wordpress-custom-cta-plugin.webp?p=8001&w=500&h=0&c=0 500w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/a2ebd2f58964\/wordpress-custom-cta-plugin.webp?p=8001&w=640&h=0&c=0 640w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/e1c1899a0272\/wordpress-custom-cta-plugin.webp?p=8001&w=800&h=0&c=0 800w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/e5fdc12b4f1b\/wordpress-custom-cta-plugin.webp?p=8001&w=1024&h=0&c=0 1024w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/0f40a552d530\/wordpress-custom-cta-plugin.webp?p=8001&w=1280&h=0&c=0 1280w, https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/4920e46e6af7\/wordpress-custom-cta-plugin.webp?p=8001&w=1600&h=0&c=0 1600w\" class=\"alignnone wp-image-8017 size-full\" title=\"test Phuket Web Design 06 11 2025 01 26 AM\" fifu-data-src=\"https:\/\/wp.fifu.app\/danielepais.com\/aHR0cHM6Ly9kYW5pZWxlcGFpcy5jb20vam91cm5hbC93cC1jb250ZW50L3VwbG9hZHMvMjAyNS8wNi90ZXN0LVBodWtldC1XZWItRGVzaWduLTA2LTExLTIwMjVfMDFfMjZfQU0uanBn\/de631fd83cf3\/wordpress-custom-cta-plugin.webp?p=8001\" alt=\"test Phuket Web Design 06 11 2025 01 26 AM\" width=\"1860\" height=\"929\" \/><\/p>\n<hr data-sourcepos=\"900:1-900:3\" \/>\n<h2 data-sourcepos=\"902:1-902:49\"><span class=\"ez-toc-section\" id=\"Section_6_Final_Touches_Best_Practices\"><\/span>Section 6: Final Touches &amp; Best Practices<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p data-sourcepos=\"904:1-904:91\">Now that you&#8217;ve built and implemented your custom CTA plugin, here are some important tips:<\/p>\n<ul data-sourcepos=\"906:1-917:0\">\n<li data-sourcepos=\"906:1-906:274\"><strong>File Permissions:<\/strong> If you ever encounter issues with your CSS or JS files not updating after plugin reactivation, check your server&#8217;s file permissions. <span class=\"citation-19\">The <\/span><code><span class=\"citation-19\">css<\/span><\/code><span class=\"citation-19\"> and <\/span><code><span class=\"citation-19\">js<\/span><\/code><span class=\"citation-19\"> folders should typically be <\/span><code><span class=\"citation-19\">755<\/span><\/code><span class=\"citation-19\">, and the <\/span><code><span class=\"citation-19\">.css<\/span><\/code><span class=\"citation-19\"> and <\/span><code><span class=\"citation-19\">.js<\/span><\/code><span class=\"citation-19\"> files themselves <\/span><code><span class=\"citation-19\">644<\/span><\/code><span class=\"citation-19 citation-end-19\">.<\/span>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<li data-sourcepos=\"907:1-910:136\"><strong>Clear Caches:<\/strong> Always, always, always clear your caches after making plugin changes! This includes:\n<ul data-sourcepos=\"908:5-910:136\">\n<li data-sourcepos=\"908:5-908:108\"><strong>WordPress Caching Plugins:<\/strong> If you use one (WP Super Cache, LiteSpeed Cache, W3 Total Cache, etc.).<\/li>\n<li data-sourcepos=\"909:5-909:84\"><strong>Server-Side Caching:<\/strong> If your host provides it (e.g., Cloudflare, Varnish).<\/li>\n<li data-sourcepos=\"910:5-910:136\"><strong><span class=\"citation-18\">Browser Cache:<\/span><\/strong><span class=\"citation-18 citation-end-18\"> Perform a hard refresh (Ctrl+F5 or Cmd+Shift+R) to ensure your browser loads the freshest files.<\/span>\n<div class=\"source-inline-chip-container ng-star-inserted\">\u00a0<\/div>\n<\/li>\n<\/ul>\n<\/li>\n<li data-sourcepos=\"911:1-911:164\"><strong>Security:<\/strong> We&#8217;ve used WordPress&#8217;s sanitization functions, which is a great start. Always be mindful of input validation and output escaping in any custom code.<\/li>\n<li data-sourcepos=\"912:1-917:0\"><strong>Further Customization Ideas:<\/strong>\n<ul data-sourcepos=\"913:5-917:0\">\n<li data-sourcepos=\"913:5-913:113\"><strong>More Layouts:<\/strong> Add options in the admin to choose between image-left, image-right, or image-top layouts.<\/li>\n<li data-sourcepos=\"914:5-914:88\"><strong>Custom Fonts:<\/strong> Integrate Google Fonts or other font options for titles\/buttons.<\/li>\n<li data-sourcepos=\"915:5-915:120\"><strong>Animations:<\/strong> Use a JavaScript library like AOS (Animate On Scroll) to make CTAs animate as they come into view.<\/li>\n<li data-sourcepos=\"916:5-917:0\"><strong>Pre-made Templates:<\/strong> Allow users to choose from a few pre-designed CTA templates.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr data-sourcepos=\"918:1-918:3\" \/>\n<h3 data-sourcepos=\"920:1-920:46\"><span class=\"ez-toc-section\" id=\"One_Last_Tip\"><\/span>One Last Tip<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In some server, I have noticed that the color customizer feature for the CTA button only works <span style=\"background-color: #ff0000; color: #ffffff;\">AFTER YOU HAVE SAVED THE CTA<\/span>.<\/p>\n<hr \/>\n<h2 data-sourcepos=\"920:1-920:46\"><span class=\"ez-toc-section\" id=\"Conclusion_Empowering_Your_WordPress_Site\"><\/span>Conclusion: Empowering Your WordPress Site<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p data-sourcepos=\"922:1-922:243\">You&#8217;ve just built a powerful, flexible, and completely custom Call-to-Action plugin for your WordPress site! This not only gives you full control over your marketing messages but also deepens your understanding of WordPress plugin development.<\/p>\n<p data-sourcepos=\"924:1-924:151\">By mastering this technique, you can create tailor-made solutions that perfectly fit your site&#8217;s needs, without relying on bloated third-party plugins.<\/p>\n<p data-sourcepos=\"926:1-926:60\">Go forth and create compelling Call-to-Actions that convert!<\/p>\n<div class=\"boxlink\">GET YOUR FREE COPY: <a title=\"Download the FREE WordPress CTA Plugin\" href=\"https:\/\/danielepais.com\/journal\/free-downloads\" target=\"_blank\" rel=\"noopener\" data-wpel-link=\"internal\">Download the FREE WordPress CTA Plugin<\/a><\/div>\n<p>And here (below)\u00a0 is the live and interactive version of the CTA plugin for WordPress:<\/p>\n        <div class=\"my-custom-cta-block\">\n                            <div class=\"my-custom-cta-image\">\n                    <img decoding=\"async\" src=\"https:\/\/danielepais.com\/journal\/wp-content\/uploads\/2023\/11\/Word-Count.jpg\" alt=\"5 Minutes Tutorial\">\n                <\/div>\n            \n            <div class=\"my-custom-cta-content\">\n                                    <h3 class=\"my-custom-cta-title\"><span class=\"ez-toc-section\" id=\"5_Minutes_Tutorial\"><\/span>5 Minutes Tutorial<span class=\"ez-toc-section-end\"><\/span><\/h3>\n                \n                                    <p class=\"my-custom-cta-subtitle\">Making a Word Count Google <a href=\"https:\/\/danielepais.com\/journal\/build-your-own-chrome-extension-editorial-plan-prompt-generator-privacy-first-no-subscriptions\/\">Chrome<\/a> Extension<\/p>\n                \n                                    <div class=\"my-custom-cta-paragraph\">If you\u2019re a freelance writer who regularly creates articles for various websites, you\u2019ve probably found yourself frequently checking the word count of your content.<\/div>\n                \n                                    <div class=\"my-custom-cta-button\">\n                        <a href=\"https:\/\/danielepais.com\/journal\/5-minutes-tutorial-making-a-word-count-google-chrome-extension\/\" class=\"button\" style=\"background-color:#2dc1a9;color:#ffffff !important;\">READ FULL ARTICLE<\/a>\n                    <\/div>\n                            <\/div>\n        <\/div>\n        \n","protected":false},"excerpt":{"rendered":"<p>Master custom CTA plugin development for WordPress. This tutorial guides you to build powerful, customizable CTAs with color pickers, images &amp; shortcodes. Gain full control! Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":8024,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"default","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[562,561,233],"tags":[],"acf":[],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.8 - aioseo.com -->\n\t<meta name=\"description\" content=\"Master custom CTA plugin development for WordPress. This tutorial guides you to build powerful, customizable CTAs with color pickers, images &amp; shortcodes. Gain full control! Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Daniele Pais\"\/>\n\t<meta name=\"google-site-verification\" content=\"googleb91c9505ed997b99\" \/>\n\t<meta name=\"msvalidate.01\" content=\"AD1C96C338E051848BE08C67378B20CA\" \/>\n\t<meta name=\"keywords\" content=\"web design,web development,wordpress\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.8\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Daniele Pais Blog\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"WordPress Custom CTA Plugin: Build &amp; Customize Your Own | Phuket Web Design\" \/>\n\t\t<meta property=\"og:description\" content=\"Master custom CTA plugin development for WordPress. This tutorial guides you to build powerful, customizable CTAs with color pickers, images &amp; shortcodes. Gain full control! Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/danielepais.com\/journal\/wp-content\/uploads\/2025\/06\/WordPress-Custom-CTA-Plugin.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/danielepais.com\/journal\/wp-content\/uploads\/2025\/06\/WordPress-Custom-CTA-Plugin.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"850\" \/>\n\t\t<meta property=\"og:image:height\" content=\"400\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2025-06-11T03:53:25+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2025-06-11T04:16:37+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:site\" content=\"@daniele_pais\" \/>\n\t\t<meta name=\"twitter:title\" content=\"WordPress Custom CTA Plugin: Build &amp; Customize Your Own | Phuket Web Design\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Master custom CTA plugin development for WordPress. This tutorial guides you to build powerful, customizable CTAs with color pickers, images &amp; shortcodes. Gain full control! Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/danielepais.com\/journal\/wp-content\/uploads\/2017\/10\/daniele-pais-digital-design.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#article\",\"name\":\"WordPress Custom CTA Plugin: Build & Customize Your Own | Phuket Web Design\",\"headline\":\"WordPress Custom CTA Plugin: Build &#038; Customize Your Own\",\"author\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/author\\\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/#person\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/WordPress-Custom-CTA-Plugin.jpg\",\"width\":850,\"height\":400,\"caption\":\"WordPress Custom CTA Plugin\"},\"datePublished\":\"2025-06-11T10:53:25+07:00\",\"dateModified\":\"2025-06-11T11:16:37+07:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#webpage\"},\"articleSection\":\"Web Design, Web Development, Wordpress\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/danielepais.com\\\/journal\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/category\\\/web\\\/#listItem\",\"name\":\"Web\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/category\\\/web\\\/#listItem\",\"position\":2,\"name\":\"Web\",\"item\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/category\\\/web\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/category\\\/web\\\/wordpress\\\/#listItem\",\"name\":\"Wordpress\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/category\\\/web\\\/wordpress\\\/#listItem\",\"position\":3,\"name\":\"Wordpress\",\"item\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/category\\\/web\\\/wordpress\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#listItem\",\"name\":\"WordPress Custom CTA Plugin: Build &#038; Customize Your Own\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/category\\\/web\\\/#listItem\",\"name\":\"Web\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#listItem\",\"position\":4,\"name\":\"WordPress Custom CTA Plugin: Build &#038; Customize Your Own\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/category\\\/web\\\/wordpress\\\/#listItem\",\"name\":\"Wordpress\"}}]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/#person\",\"name\":\"Daniele Pais\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#personImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/86bedf0ab24a6d4a4f32de230cc797ef?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Daniele Pais\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/author\\\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\\\/#author\",\"url\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/author\\\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\\\/\",\"name\":\"Daniele Pais\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/86bedf0ab24a6d4a4f32de230cc797ef?s=96&d=mm&r=g\",\"width\":96,\"height\":96,\"caption\":\"Daniele Pais\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#webpage\",\"url\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/\",\"name\":\"WordPress Custom CTA Plugin: Build & Customize Your Own | Phuket Web Design\",\"description\":\"Master custom CTA plugin development for WordPress. This tutorial guides you to build powerful, customizable CTAs with color pickers, images & shortcodes. Gain full control! Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/author\\\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/author\\\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\\\/#author\"},\"image\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wp-content\\\/uploads\\\/2025\\\/06\\\/WordPress-Custom-CTA-Plugin.jpg\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#mainImage\",\"width\":850,\"height\":400,\"caption\":\"WordPress Custom CTA Plugin\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/wordpress-custom-cta-plugin-build-customize-your-own\\\/#mainImage\"},\"datePublished\":\"2025-06-11T10:53:25+07:00\",\"dateModified\":\"2025-06-11T11:16:37+07:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/#website\",\"url\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/\",\"name\":\"Phuket Web Design\",\"description\":\"Digital Print\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/danielepais.com\\\/journal\\\/#person\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"WordPress Custom CTA Plugin: Build & Customize Your Own | Phuket Web Design","description":"Master custom CTA plugin development for WordPress. This tutorial guides you to build powerful, customizable CTAs with color pickers, images & shortcodes. Gain full control! Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors","canonical_url":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/","robots":"max-image-preview:large","keywords":"web design,web development,wordpress","webmasterTools":{"google-site-verification":"googleb91c9505ed997b99","msvalidate.01":"AD1C96C338E051848BE08C67378B20CA","miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#article","name":"WordPress Custom CTA Plugin: Build & Customize Your Own | Phuket Web Design","headline":"WordPress Custom CTA Plugin: Build &#038; Customize Your Own","author":{"@id":"https:\/\/danielepais.com\/journal\/author\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\/#author"},"publisher":{"@id":"https:\/\/danielepais.com\/journal\/#person"},"image":{"@type":"ImageObject","url":"https:\/\/danielepais.com\/journal\/wp-content\/uploads\/2025\/06\/WordPress-Custom-CTA-Plugin.jpg","width":850,"height":400,"caption":"WordPress Custom CTA Plugin"},"datePublished":"2025-06-11T10:53:25+07:00","dateModified":"2025-06-11T11:16:37+07:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#webpage"},"isPartOf":{"@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#webpage"},"articleSection":"Web Design, Web Development, Wordpress"},{"@type":"BreadcrumbList","@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal#listItem","position":1,"name":"Home","item":"https:\/\/danielepais.com\/journal","nextItem":{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal\/category\/web\/#listItem","name":"Web"}},{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal\/category\/web\/#listItem","position":2,"name":"Web","item":"https:\/\/danielepais.com\/journal\/category\/web\/","nextItem":{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal\/category\/web\/wordpress\/#listItem","name":"Wordpress"},"previousItem":{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal\/category\/web\/wordpress\/#listItem","position":3,"name":"Wordpress","item":"https:\/\/danielepais.com\/journal\/category\/web\/wordpress\/","nextItem":{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#listItem","name":"WordPress Custom CTA Plugin: Build &#038; Customize Your Own"},"previousItem":{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal\/category\/web\/#listItem","name":"Web"}},{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#listItem","position":4,"name":"WordPress Custom CTA Plugin: Build &#038; Customize Your Own","previousItem":{"@type":"ListItem","@id":"https:\/\/danielepais.com\/journal\/category\/web\/wordpress\/#listItem","name":"Wordpress"}}]},{"@type":"Person","@id":"https:\/\/danielepais.com\/journal\/#person","name":"Daniele Pais","image":{"@type":"ImageObject","@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#personImage","url":"https:\/\/secure.gravatar.com\/avatar\/86bedf0ab24a6d4a4f32de230cc797ef?s=96&d=mm&r=g","width":96,"height":96,"caption":"Daniele Pais"}},{"@type":"Person","@id":"https:\/\/danielepais.com\/journal\/author\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\/#author","url":"https:\/\/danielepais.com\/journal\/author\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\/","name":"Daniele Pais","image":{"@type":"ImageObject","@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/86bedf0ab24a6d4a4f32de230cc797ef?s=96&d=mm&r=g","width":96,"height":96,"caption":"Daniele Pais"}},{"@type":"WebPage","@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#webpage","url":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/","name":"WordPress Custom CTA Plugin: Build & Customize Your Own | Phuket Web Design","description":"Master custom CTA plugin development for WordPress. This tutorial guides you to build powerful, customizable CTAs with color pickers, images & shortcodes. Gain full control! Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/danielepais.com\/journal\/#website"},"breadcrumb":{"@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#breadcrumblist"},"author":{"@id":"https:\/\/danielepais.com\/journal\/author\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\/#author"},"creator":{"@id":"https:\/\/danielepais.com\/journal\/author\/_-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2-2--2\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/danielepais.com\/journal\/wp-content\/uploads\/2025\/06\/WordPress-Custom-CTA-Plugin.jpg","@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#mainImage","width":850,"height":400,"caption":"WordPress Custom CTA Plugin"},"primaryImageOfPage":{"@id":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/#mainImage"},"datePublished":"2025-06-11T10:53:25+07:00","dateModified":"2025-06-11T11:16:37+07:00"},{"@type":"WebSite","@id":"https:\/\/danielepais.com\/journal\/#website","url":"https:\/\/danielepais.com\/journal\/","name":"Phuket Web Design","description":"Digital Print","inLanguage":"en-US","publisher":{"@id":"https:\/\/danielepais.com\/journal\/#person"}}]},"og:locale":"en_US","og:site_name":"Daniele Pais Blog","og:type":"article","og:title":"WordPress Custom CTA Plugin: Build &amp; Customize Your Own | Phuket Web Design","og:description":"Master custom CTA plugin development for WordPress. This tutorial guides you to build powerful, customizable CTAs with color pickers, images &amp; shortcodes. Gain full control! Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors","og:url":"https:\/\/danielepais.com\/journal\/wordpress-custom-cta-plugin-build-customize-your-own\/","og:image":"https:\/\/danielepais.com\/journal\/wp-content\/uploads\/2025\/06\/WordPress-Custom-CTA-Plugin.jpg","og:image:secure_url":"https:\/\/danielepais.com\/journal\/wp-content\/uploads\/2025\/06\/WordPress-Custom-CTA-Plugin.jpg","og:image:width":850,"og:image:height":400,"article:published_time":"2025-06-11T03:53:25+00:00","article:modified_time":"2025-06-11T04:16:37+00:00","twitter:card":"summary","twitter:site":"@daniele_pais","twitter:title":"WordPress Custom CTA Plugin: Build &amp; Customize Your Own | Phuket Web Design","twitter:description":"Master custom CTA plugin development for WordPress. This tutorial guides you to build powerful, customizable CTAs with color pickers, images &amp; shortcodes. Gain full control! Are you tired of relying on bloated plugins or scattered hardcoded HTML for your Call-to-Action (CTA) blocks? Do you crave complete control over your CTAs, from their content and colors","twitter:image":"https:\/\/danielepais.com\/journal\/wp-content\/uploads\/2017\/10\/daniele-pais-digital-design.png"},"aioseo_meta_data":{"post_id":"8001","title":null,"description":null,"keywords":null,"keyphrases":{"focus":{"keyphrase":"custom CTA plugin","score":78,"analysis":{"keyphraseInTitle":{"score":9,"maxScore":9,"error":0},"keyphraseInDescription":{"score":9,"maxScore":9,"error":0},"keyphraseLength":{"score":9,"maxScore":9,"error":0,"length":3},"keyphraseInURL":{"score":5,"maxScore":5,"error":0},"keyphraseInIntroduction":{"score":9,"maxScore":9,"error":0},"keyphraseInSubHeadings":{"score":3,"maxScore":9,"error":1},"keyphraseInImageAlt":{"score":9,"maxScore":9,"error":0},"keywordDensity":{"score":0,"type":"low","maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"Article","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"created":"2025-06-10 16:53:01","updated":"2025-06-11 19:15:42","ai":null,"seo_analyzer_scan_date":null},"_links":{"self":[{"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/posts\/8001"}],"collection":[{"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/comments?post=8001"}],"version-history":[{"count":0,"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/posts\/8001\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/media\/8024"}],"wp:attachment":[{"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/media?parent=8001"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/categories?post=8001"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/danielepais.com\/journal\/wp-json\/wp\/v2\/tags?post=8001"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}