<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>WordPress &#8211; Cloud Nine Apps</title>
	<atom:link href="https://cloudnineapps.com/blogs/wordpress/feed/" rel="self" type="application/rss+xml" />
	<link>https://cloudnineapps.com</link>
	<description>Simplifying Technology</description>
	<lastBuildDate>Sat, 20 Apr 2019 14:11:55 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.4.16</generator>

<image>
	<url>https://i2.wp.com/cloudnineapps.com/wp-content/uploads/cropped-CloudNineApps_favicon-2.png?fit=32%2C32&#038;ssl=1</url>
	<title>WordPress &#8211; Cloud Nine Apps</title>
	<link>https://cloudnineapps.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">136749396</site>	<item>
		<title>Manage Your WordPress Content Smartly</title>
		<link>https://cloudnineapps.com/blogs/wordpress/manage-your-wordpress-content-smartly/</link>
					<comments>https://cloudnineapps.com/blogs/wordpress/manage-your-wordpress-content-smartly/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Mon, 18 Jun 2018 20:42:18 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=1200</guid>

					<description><![CDATA[<p>Manage Your WordPress Content Smartly As content authors and bloggers you always want to offer the most useful content to the readers. You want to make it easy for them to find the right information. At the same time, as&#8230;&#160;<a href="https://cloudnineapps.com/blogs/wordpress/manage-your-wordpress-content-smartly/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/manage-your-wordpress-content-smartly/">Manage Your WordPress Content Smartly</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Manage Your WordPress Content Smartly</h1>
<p>As content authors and bloggers you always want to offer the most useful content to the readers. You want to make it easy for them to find the right information. At the same time, as your content grows you want to make sure that it is easy to maintain. In this post, I will talk about some basic to advanced tips on how to manage your WordPress content smartly. If you are already an avid WordPress user, you can jump to the <a href="#advanced_tips">advanced tips</a>. Please use these as the basis to get you started. If you would like to share any tips that you have found useful, please feel free to share in the comments.</p>
<h2>Basic Content Management Tips</h2>
<h3>Decide a good URL naming convention</h3>
<p>Content Management systems like WordPress make it a breeze to publish content. However, it is important to understand what URL will be formed and it is a good idea to choose a pattern that aligns with your needs the best. Following are some basic guidelines.</p>
<ul>
<li>If your site is mostly static pages (not regular blogs), a URL pattern like <code>http://site/%category%/%post%</code> is a good choice. An example URL using this convention is <a href="https://cloudnineapps.com/products/wordpress-plugins">https://cloudnineapps.com/products/wordpress-plugins</a>.</li>
<li>If you publish content at regular interval, such as, regular blog posts, a URL pattern like <code>http://site/%year%/%monthnum%/%postname%/</code> is a good choice. An example would be <code>https://cloudnineapps.com/2018/06/smart-wordpress-content</code>. This makes it easy to put a time context in your URL. Also, by having the post title in the URL, you still have an SEO friendly URL.</li>
</ul>
<div class="su-box su-box-style-default" id="" style="border-color:#720009;border-radius:5px"><div class="su-box-title" style="background-color:#a5203c;color:#FFFFFF;border-top-left-radius:3px;border-top-right-radius:3px">Tip</div><div class="su-box-content su-u-clearfix su-u-trim" style="border-bottom-left-radius:3px;border-bottom-right-radius:3px">
<ul>
<li>URL pattern can be changed via <strong>WordPress Admin-&gt;Settings-&gt;Permalinks</strong>.</li>
<li>By default, WordPress does not provide category support for pages. However, there is a a neat plugin for this &#8211; <a href="https://wordpress.org/plugins/post-tags-and-categories-for-pages/" target="_blank" rel="noopener">Post Tags and Categories for Pages</a>.</li>
</div></div></ul>
<h3>Posts vs Pages</h3>
<p>I know, I know. This must have been discussed numerous times before. But, it is critical to understand when to use which one. Here are some guidelines.</p>
<h4>When to use a Page?</h4>
<ul>
<li>A Page is a good candidate for static content or content that does not change very often. A good example would be about us, privacy policy, home page. In addition, if you sell products or other content, setting up page for each such content is a good idea.</li>
<li>You can also use Page for helping with site navigation. For example, at Cloud Nine Apps, we use pages to organize the menu navigation links. So, when a user clicks on these menu links, they get a nice summary of that menu as opposed to a blog post view that may chop off content. Take a look at the couple links below to get a feel.<br />
<a href="https://cloudnineapps.com/products/wordpress-plugins/" target="_blank" rel="noopener">https://cloudnineapps.com/products/wordpress-plugins/</a><br />
<a href="https://cloudnineapps.com/support/" target="_blank" rel="noopener">https://cloudnineapps.com/support/</a></li>
</ul>
<h4>When to use a Post?</h4>
<ul>
<li>Post is a great choice for regularly authored content, such as, blogs.</li>
<li>WordPress provides several out-of-the-box capabilities to present posts, such as, organizing posts in categories and search posts (that also shows post excerpts).</li>
<li>If you are interested in WordPress plugin development, you will particularly find post interesting as it is the base object for WordPress content including any custom content type (a.k.a. <strong>custom post type</strong>) that you may develop. If you would like to learn more about plugin development, please check out <a href="https://cloudnineapps.com/blogs/writing-your-first-wordpress-plugin/" target="_blank" rel="noopener">Writing Your First WordPress Plugin</a>.</li>
</ul>
<h3>Organizing Media Content</h3>
<p>When talking about content management, it is important to keep any media content in mind as well. This is a very likely candidate that can get easily disorganized making it harder to find the most relevant content. The good news is you can organize media content as well. I prefer to organize media content in a well-defined folder structure. Here is an example.</p>
<pre>|- wp-content
| |- uploads
| | |- blogs
| | | |- blog-post-1
| | | | |- media1.png
| | | |- blog-post-2
| | |- products
| | | |- product-1
| | | | |- logo.png
| | | | |- demo.mp4
| | | |- product-2
</pre>
<p>As a content author, this makes locating media more easy and you can keep building on top of it. In order to use media this way, you simply need to upload content under the WordPress uploads folder (similar to the one shown above) and use a plugin like <a href="https://wordpress.org/plugins/media-library-plus/" target="_blank" rel="noopener">Media Library Folders for WordPress</a> to sync folders and regenerate the thumbnails.</p>
<h2><a name="advanced_tips"></a>Advanced Content Management Tips</h2>
<p>Let&#8217;s talk about the text content itself now, which is the bulk of content for a vast majority of sites. How can you manage it more smartly? Here are some thoughts.</p>
<ul>
<li>Dissect your content to see if it can be modularized. For example, you may have several blog posts and pages that repeat the setup instructions, product features, etc. Tomorrow, if you were to add another step or amend this content, you have to update all these posts/pages. So, when you look at modularization, think of reusability aspect.</li>
<li>Do you have content that is constantly changing, such as, promotion codes, coupons, etc? And, there are links all over your site. If you change the coupon code, you have to update in multiple places.</li>
<li>Lastly, when you work on big content releases, at times you may want to put all the content out there, but not make it open to public yet. Only make it available to a few selected users. And, when time comes, you want to simply hit a magic button to make the content live!</li>
</ul>
<p>This is precisely where our content management plugins <a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/" target="_blank" rel="noopener">C9 Variables</a> (free) and <a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/" target="_blank" rel="noopener">C9 Variables Pro</a> (paid) come in handy.</p>
<div class="alignleft"><a href="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?ssl=1"><img class="alignnone size-medium wp-image-727" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=300%2C97&#038;ssl=1" alt="" width="300" height="97" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=300%2C97&amp;ssl=1 300w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=768%2C249&amp;ssl=1 768w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=1024%2C332&amp;ssl=1 1024w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=320%2C104&amp;ssl=1 320w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=640%2C207&amp;ssl=1 640w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=360%2C117&amp;ssl=1 360w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=720%2C233&amp;ssl=1 720w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=1080%2C350&amp;ssl=1 1080w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=800%2C259&amp;ssl=1 800w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?resize=1280%2C415&amp;ssl=1 1280w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-banner.png?w=1544&amp;ssl=1 1544w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /> </a></div>
<p>These let you define the reusable content as variables. Then, you can simply use the convenient <code>c9-vars-insert</code> shortcode in posts and pages to use these variables. And, when these posts/pages are shown the plugin dynamically gets the variable value to show the full post/page. This way you get 2 benefits straightway.</p>
<ol>
<li>Avoid content repetition.</li>
<li>Whenever you have an update for the variable content, simply update the variable in one place and all referring posts/pages will see the latest value.</li>
</ol>
<p>These plugins integrate into the WordPress visual editor itself making it easy to lookup and insert variables. If you would like to see these in action, please see the <a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/c9-variables-demo/" target="_blank" rel="noopener">C9 Variables Demo</a>.</p>
<p>The free plugin is fully functional and supports up to 10 variables. So, go ahead and give it a try. The Pro plugin offers unlimited variables support along with more productivity enhancement features (such as, mark favorite variables and use most recently used variables).</p>
<h2>Conclusion</h2>
<p>Whether you have a website with static pages or a dynamic website that is constantly enriched by posts, it is crucial to have a content management strategy. It starts with basic things like URL naming conventions, using pages vs posts and organizing media content. Then, to manage your page and post content more smartly, consider use of plugins like <a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/" target="_blank" rel="noopener">C9 Variables</a> and <a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/" target="_blank" rel="noopener">C9 Variables Pro</a> that make it easy to define and manage reusable content.</p>
<p>Happy authoring!<br />
&#8211; Nitin</p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Build smart reusable content that is easy to maintain.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/"><img class="wp-image-728 size-full aligncenter" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-small.png?resize=128%2C128&#038;ssl=1" alt="" width="128" height="128" data-recalc-dims="1" /></a></p>
<center><strong><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/">C9 Variables</a> (FREE)</strong></center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/"><img class="wp-image-663 size-full aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables-pro/c9-variables-pro-small.png?resize=128%2C128&#038;ssl=1" alt="" width="128" height="128" data-recalc-dims="1" /></a></p>
<center><strong><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/">C9 Variables Pro</a></strong></center>
<p></div></div> </div></div></div></p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fmanage-your-wordpress-content-smartly%2F&amp;linkname=Manage%20Your%20WordPress%20Content%20Smartly" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fmanage-your-wordpress-content-smartly%2F&amp;linkname=Manage%20Your%20WordPress%20Content%20Smartly" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fmanage-your-wordpress-content-smartly%2F&amp;linkname=Manage%20Your%20WordPress%20Content%20Smartly" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fmanage-your-wordpress-content-smartly%2F&amp;linkname=Manage%20Your%20WordPress%20Content%20Smartly" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fmanage-your-wordpress-content-smartly%2F&#038;title=Manage%20Your%20WordPress%20Content%20Smartly" data-a2a-url="https://cloudnineapps.com/blogs/wordpress/manage-your-wordpress-content-smartly/" data-a2a-title="Manage Your WordPress Content Smartly"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/manage-your-wordpress-content-smartly/">Manage Your WordPress Content Smartly</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/wordpress/manage-your-wordpress-content-smartly/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1200</post-id>	</item>
		<item>
		<title>Writing Your First WordPress Plugin</title>
		<link>https://cloudnineapps.com/blogs/wordpress/writing-your-first-wordpress-plugin/</link>
					<comments>https://cloudnineapps.com/blogs/wordpress/writing-your-first-wordpress-plugin/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Mon, 21 May 2018 21:33:09 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=1050</guid>

					<description><![CDATA[<p>Writing Your First WordPress Plugin With WordPress powering over 25% of websites, it is undoubtedly a platform of interest to many developers and entrepreneurs as it brings in many opportunities to participate, contribute and even make money. Having published first&#8230;&#160;<a href="https://cloudnineapps.com/blogs/wordpress/writing-your-first-wordpress-plugin/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/writing-your-first-wordpress-plugin/">Writing Your First WordPress Plugin</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Writing Your First WordPress Plugin</h1>
<p>With WordPress powering <a href="https://www.forbes.com/sites/montymunford/2016/12/22/how-wordpress-ate-the-internet-in-2016-and-the-world-in-2017/#595d852a199d">over 25% of websites</a>, it is undoubtedly a platform of interest to many developers and entrepreneurs as it brings in many opportunities to participate, contribute and even make money. Having published first set of plugins (<a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/">C9 Variables Pro</a> and <a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/">C9 Variables</a>), I wanted to share my learning on how to write your first WordPress plugin along with a few tips.</p>
<h2>Why write a WordPress plugin?</h2>
<div class="alignright"><iframe width="560" height="315" src="https://www.youtube.com/embed/-XzlURjFX6E" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen="allowfullscreen"></iframe><center></p>
<p><strong>My talk at the Boston WordPress Meetup @Harvard University</strong></p>
<p></center></div>
<p>A WordPress plugin lets you extend the WordPress platform to provide value to users. It could be as simple as showing custom text to a full blown E-commerce solution. The possibilities are endless! If you are a developer or have a great plugin idea, here are some good reasons to write a WordPress plugin.</p>
<ul>
<li>WordPress is a popular platform. So, you have a huge potential market.</li>
<li>The WordPress platform makes it quite easy to extend and write your own plugin.</li>
<li>The overall WordPress ecosystem has made it easy to publish and manage plugins. Be it for free or for commercial purpose.</li>
<li>If you are looking at selling your plugin, there are well-established sites out there which can do this. In addition, you can also sell on your own.</li>
<li>Having developed in many languages and frameworks in the past, I can say from experience that it is fun writing code on top of WordPress platform.</li>
</ul>
<p>Keep in mind though that there are several thousands of plugins already out there. Do not let the number overwhelm you. Just make sure whichever plugin you write has originality and delivers real value to the users.</p>
<h2>Plugin Development Cycle</h2>
<p>A picture is worth a thousand words. The following flowchart captures the essence of a typical Plugin Development Cycle.</p>
<p><a href="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?ssl=1"><img class="alignnone wp-image-1089 size-medium" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=300%2C187&#038;ssl=1" alt="WordPress Plugin Development Cycle" width="300" height="187" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=300%2C187&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=768%2C479&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=1024%2C638&amp;ssl=1 1024w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=320%2C200&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=640%2C399&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=360%2C224&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=720%2C449&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=1080%2C673&amp;ssl=1 1080w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=800%2C499&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?resize=1280%2C798&amp;ssl=1 1280w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Development_Cycle.png?w=1296&amp;ssl=1 1296w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></p>
<p>Here are the key points.</p>
<ul>
<li>Come up with a plugin idea. The key being something that delivers value to the users. Here are some inputs.
<ul>
<li>What kind of challenges you have seen when you built/manage your site? Are there any good plugins out there that solve these? If not, there&#8217;s your idea.
<ul>
<li>A case in point is when I was authoring my blogs and organizing site content, I felt a need to modularize my content so that I can reuse the same content across multiple pages and posts. Also, make it easy to manage changes to such reusable content in one place. An example of this was product features. That&#8217;s how  <a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/">C9 Variables</a> was born.</li>
</ul>
</li>
<li>You may already be a domain expert and have an idea of typical challenges people face. So, you could write a plugin that can help people overcome these. Bingo!</li>
<li>In software world, many times we ask &#8220;what problem are you trying to solve?&#8221; I like to ask &#8220;what value are you trying to bring?&#8221; So, you see, not everything has to be thought in terms of a problem and a solution. You may have ideas around how to do things better or may be altogether a new concept.</li>
<li>Lastly, no matter which idea(s) you choose, try to start simple and not invest a lot of time and energy unless you are absolutely sure it&#8217;s worth the time. As Entrepreneurs and developers we often juggle through various tasks and priorities. So, it&#8217;s worth getting a reasonable plugin out, get some feedback and then build more as opposed to taking a long time and delivering something that does not get used as much.</li>
</ul>
</li>
<li>Develop the plugin. I would specifically like to highlight to focus on quality and ensuring you have good unit testing in place. This can save you far more hassles and support requests. Besides, writing good unit tests is fun!</li>
<li>How do you plan to release the plugin?
<ul>
<li>Is it free? In that case WordPress.org is perhaps the best plugin directory to submit to.</li>
<li>If paid
<ul>
<li>Are you planning to use an existing marketplace like <a href="https://codecanyon.net/">Code Canyon</a>? They take a decent cut out of the sales. But, they do provide a rich platform that makes it easy to sell plugin.</li>
<li>Lastly, you can always sell the plugin on your own site. More work for sure. But, there are several WordPress plugins (such as, <a href="https://woocommerce.com/">WooCommerce</a>) that can help.</li>
</ul>
</li>
</ul>
</li>
<li>In general, submission to any site/directory goes through an initial review process. This typically involves things like adhering to the WordPress <a href="https://codex.wordpress.org/WordPress_Coding_Standards">coding standards</a> and any other site specific guidelines.</li>
<li>Finally, make the release along with a good documentation, tutorial, demo and perhaps a video as well to make it easy for users to consume it.</li>
<li>And, the journey has begun! Make sure to stay on top of support requests, customer queries. Be helpful.</li>
<li>Many a times the support requests and user inputs may give you enough for the next release. On top of that you could come up with even more ideas to make the plugin more useful.</li>
</ul>
<h2>Developing Your Plugin</h2>
<h3>Let&#8217;s build a plugin together</h3>
<p>Yes! What else would be a better way to show? Let&#8217;s make a simple plugin &#8211; <strong>WordPress Talks</strong>, which provides the following capabilities.</p>
<ul>
<li>WordPress Admin
<ul>
<li>Capture the talk Title and Description</li>
<li>Capture the Presenter Name, Website and Recording URL</li>
<li>Settings
<ul>
<li>Enable/disable debug mode</li>
</ul>
</li>
</ul>
</li>
<li>WordPress Public
<ul>
<li>Embed list of talks in a page or post</li>
<li>Embed a specific talk in a page or post</li>
</ul>
</li>
</ul>
<p>We&#8217;ll use a plugin <strong>slug</strong> &#8211; <strong>c9-wp-talks</strong>, for the sake of keeping it unique. A slug is a unique string that is part of the URL (in this case for our plugin). It is important to have a unique slug esp. when you submit it to a plugin directory like WordPress.org to avoid any conflicts.</p>
<p><span style="text-decoration: underline;">Note</span>: See the <strong>Resources</strong> section for access to the complete code.</p>
<h3>Before you begin</h3>
<p>Rest of the post assumes you have a working WordPress installation for development, preferably. If you are looking for a jumpstart on setting up WordPress, please read <a href="https://cloudnineapps.com/blogs/getting-started-wordpress-developers-webmasters/">Getting Started with WordPress for Developers and Webmasters</a>.</p>
<p>Edit your WordPress <strong>wp-config.php</strong> to enable debug by configuring the following settings.</p>
<pre class="lang:php decode:true">define( 'WP_DEBUG', true);
define( 'WP_DEBUG_LOG', true);
</pre>
<p>This will enable logging to the <strong>wp-content/debug.log</strong> file.</p>
<h3>Get a skeleton version of plugin running in 2mins!</h3>
<p>Yes, no kidding! If you are fast you could do it in under a minute. No pressure! <img src="https://s.w.org/images/core/emoji/12.0.0-1/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
<p>WordPress recommends certain <a href="https://codex.wordpress.org/WordPress_Coding_Standards">coding standards</a>. You can obviously start from scratch or get a jumpstart by generating a skeleton code for your plugin. I recommend using a generator like the one below.<br />
<a href="https://wppb.me/">https://wppb.me/</a></p>
<p>There are a few advantages of using this tool.</p>
<ul>
<li>It generates almost fully-functional code that adheres to the WordPress standards.</li>
<li>It organizes code in a more logical structure, such as, admin vs public.</li>
<li>The generated code has well-defined methods where you can add your code.</li>
<li>The generated code is also fairly well documented.</li>
</ul>
<p>In the beginning, you may feel that it generates a lot of code. However, you can always get rid of any unnecessary code. At a minimum, it&#8217;s worth a try.</p>
<p>Here&#8217;s a screenshot of generating skeleton code for <strong>c9-wp-talks</strong>.</p>
<p><a href="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?ssl=1"><img class="alignnone wp-image-1085 size-medium" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=300%2C204&#038;ssl=1" alt="WordPress Plugin Skeleton Code Generator" width="300" height="204" srcset="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=300%2C204&amp;ssl=1 300w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=768%2C523&amp;ssl=1 768w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=1024%2C697&amp;ssl=1 1024w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=320%2C218&amp;ssl=1 320w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=640%2C436&amp;ssl=1 640w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=360%2C245&amp;ssl=1 360w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=720%2C490&amp;ssl=1 720w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=1080%2C736&amp;ssl=1 1080w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=800%2C545&amp;ssl=1 800w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?resize=1280%2C872&amp;ssl=1 1280w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Generate_Plugin_Skeleton_Code.png?w=1392&amp;ssl=1 1392w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></p>
<p>Follow these steps to use the skeleton code.</p>
<ul>
<li>Download and extract the <strong>c9-wp-talks.zip</strong> under your <strong>wp-content/plugins</strong> folder and change directory to <strong>wp-content/plugins/c9-wp-talks</strong>. We&#8217;ll refer to this as the <strong>PLUGIN_DIR</strong> in rest of the post.</li>
<li>Edit <strong>c9-wp-talks.php</strong>
<ul>
<li>Update <strong>Description</strong> in comments: <em>A simple plugin to capture WordPress talks.</em></li>
<li>Replace the <strong>PLUGIN_NAME_VERSION</strong> constant by <strong>C9_WP_TALKS_VERSION</strong>.</li>
</ul>
</li>
<li>Edit <strong>includes/class-c9-wp-talks.php</strong> and replace the <strong>PLUGIN_NAME_VERSION</strong> constant by <strong>C9_WP_TALKS_VERSION</strong>.</li>
<li>Go to WordPress Admin Plugins page and you should now see an entry for the <strong>WordPress Talks</strong> plugin waiting to be activated. I told you it was easy.<br />
<a href="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?ssl=1"><img class="alignnone wp-image-1086 size-medium" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=300%2C156&#038;ssl=1" alt="C9 WordPress Talks - Activate Plugin" width="300" height="156" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=300%2C156&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=768%2C399&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=1024%2C532&amp;ssl=1 1024w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=320%2C166&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=640%2C332&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=360%2C187&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=720%2C374&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=1080%2C561&amp;ssl=1 1080w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=800%2C416&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?resize=1280%2C665&amp;ssl=1 1280w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_Plugin_Activation.png?w=1702&amp;ssl=1 1702w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></li>
<li>Click on <strong>Activate</strong> and your plugin is now part of the WordPress ecosystem.</li>
</ul>
<h3>Figuring out the Data Model</h3>
<p>As you can imagine, we have talks data that needs to be persisted to the database. We have a couple options here.</p>
<ol>
<li>Use WordPress built-in data model.</li>
<li>Create our own database schema.</li>
</ol>
<p>In general, I highly recommend using the WordPress built-in data model for the following reasons.</p>
<ul>
<li>The built-in model is reasonably generic. You can model various types of real-world or other entities including any custom attributes these may have.
<ul>
<li>The <strong>post</strong> object is one such generic object in WordPress out-of-the-box data model that can store custom objects. Each such object is of a <strong>custom post type</strong>, which makes it easy to identify and manage objects of that type. You will often see WordPress developers interchangeably using post object for such custom objects. In fact, several of WordPress APIs as well as parameter names would refer to such objects as posts. And, that&#8217;s primarily because these objects are stored as posts.</li>
<li>Obviously, post object has well-defined columns in it&#8217;s database table. So, how do we store custom attributes that are not part of this table? Simple! The custom attributes are captured as <strong>meta data</strong>. Think of meta data as <strong>(key, value) pairs</strong> that are associated with a given post object.</li>
</ul>
</li>
<li>Apart from using the model, WordPress has a rich framework that can save you from writing additional code. Things like admin screens to perform CRUD (create/retrieve/update/delete), showing search results, etc.</li>
<li>WordPress has a fairly matured callback/<strong>hooks</strong> capability to call custom code at various points in the flow. When you use the built-in model, you get to leverage the pre-defined hooks.</li>
<li>WordPress offers an interesting capability called as <strong>multisite</strong>. In this, the same WordPress installation can support multiple sites, such as, a site per user of your site. When you use the built-in model, you automatically get the benefit of multisite compatibility by following WordPress recommended coding practices.</li>
</ul>
<p>Net-net, using the existing model is highly recommended and will give you more time to focus on the core functionality of your product. For <strong>c9-wp-talks</strong>, we will use the following.</p>
<table class="c9-settings-table">
<thead>
<tr>
<td>Custom Post Type</td>
<td>Table</td>
<td>Meta Data</td>
</tr>
</thead>
<tbody>
<tr>
<td>c9_wp_talks_talk</td>
<td>posts</td>
<td>
<ul>
<li>c9_wp_talks_presenter_name</li>
<li>c9_wp_talks_presenter_website</li>
<li>c9_wp_talks_recording_url</li>
</ul>
</td>
</tr>
</tbody>
</table>
<div class="su-note"  style="border-color:#e5e5b2;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#FFFFCC;border-color:#ffffff;color:#333333;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;">The Custom Post Type should be unique. A simple way of doing this is to use the plugin slug followed by the noun (entity) being represented as shown above.</div></div>
<h3>Understanding WordPress Hooks</h3>
<p>In order to write a WordPress plugin, you must understand WordPress hooks. In this section we will go over these briefly. When you think of writing code for a WordPress plugin, you will often have a need to execute code at various points in the flow. That&#8217;s precisely what hooks are for. This could be things like loading your stylesheets or javascripts to something more involved, such as, performing an action when data is saved. In fact, you should always refer to <a href="https://codex.wordpress.org/Plugin_API/Hooks">WordPress Hooks</a> documentation to see if there is one available to integrate your code more easily. And, a hook is essentially a <strong>callback function</strong> that is invoked when it is triggered. In essence, a WordPress plugin is developed on top of such hooks as opposed to a standalone application. It is crucial to understand this not only to be a good WordPress ecosystem citizen, but also to leverage it&#8217;s potential.</p>
<p>There are 2 types of hooks supported by WordPress.</p>
<ol>
<li><strong>Action</strong>: An action is meant to respond to an event, such as, call a function when data is saved to the database.</li>
<li><strong>Filter</strong>: A filter lets you massage data, such as, for data transformation or sanitization purpose.</li>
</ol>
<p>You can have <strong>multiple callbacks</strong> per hook. Lastly, hooks are often passed in additional parameters or can access global variables to access the data in context.</p>
<h3>Let&#8217;s write some code</h3>
<p>Let&#8217;s start writing our plugin code along with a few tips.</p>
<ul>
<li>Write your code in custom classes with well-defined names. For example, for our plugin we would use the <strong>C9_WP_Talks_</strong> prefix. This avoids potential issues like conflicting function names with other plugins. Also, avoid over-burdening a class with too many responsibility. Create more classes, as appropriate. For our simple plugin, we will write the following classes:
<ol>
<li><strong>C9_Wp_Talks_Constants</strong>: This provides common constants used throughout the code.</li>
<li><strong>C9_Wp_Talks_Admin_Delegate</strong>: This provides the core logic for admin functionality.</li>
<li><strong>C9_Wp_Talks_Admin_UI</strong>: This provides the user interface (UI) logic.</li>
<li><strong>C9_Wp_Talks_Public_Delegate</strong>: This provides the core logic for public functionality.</li>
<li><strong>C9_Log_Writer</strong>: A class to simplify logging.</li>
</ol>
</li>
<li>We will leverage the structure of the skeleton code to organize our code.<br />
<a href="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?ssl=1"><img class="alignnone wp-image-1088 size-medium" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?resize=176%2C300&#038;ssl=1" alt="Plugin Directory Structure" width="176" height="300" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?resize=176%2C300&amp;ssl=1 176w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?resize=600%2C1024&amp;ssl=1 600w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?resize=320%2C546&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?resize=640%2C1091&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?resize=360%2C614&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?resize=720%2C1228&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?resize=158%2C270&amp;ssl=1 158w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?resize=300%2C512&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Plugin_Dir_Structure.png?w=740&amp;ssl=1 740w" sizes="(max-width: 176px) 100vw, 176px" data-recalc-dims="1" /></a><br />
<span style="text-decoration: underline;">Note</span>: Notice how we are organizing our custom classes under <strong>includes/code</strong> directory structure.</li>
<li>Use the generated skeleton code to call relevant methods in the above classes. That way the skeleton code is de-coupled from the core logic.</li>
</ul>
<h4>Understanding the Code Flow</h4>
<p>We talked about a few points so far from WordPress hooks to writing custom classes for our plugin. Let&#8217;s put these in perspective by reviewing some code flows. Following sequence diagram illustrates these.</p>
<p><a href="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?ssl=1"><img class="alignnone wp-image-1090 size-medium" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?resize=300%2C194&#038;ssl=1" alt="WordPress Plugin Sample Admin Interactions" width="300" height="194" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?resize=300%2C194&amp;ssl=1 300w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?resize=768%2C496&amp;ssl=1 768w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?resize=320%2C207&amp;ssl=1 320w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?resize=640%2C413&amp;ssl=1 640w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?resize=360%2C232&amp;ssl=1 360w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?resize=720%2C465&amp;ssl=1 720w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?resize=800%2C517&amp;ssl=1 800w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/WordPress_Plugin_Sample_Admin_Interactions.png?w=1022&amp;ssl=1 1022w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></p>
<p><span style="text-decoration: underline;"><strong>Interaction#1: Plugin Initialization</strong></span></p>
<ul>
<li>We would like to register our custom post type and settings with WordPress. This is done via the WordPress <strong>init</strong> action callbacks implemented by <strong>C9_Wp_Talks_Admin_Delegate</strong>.
<ul>
<li><strong>register_cpt()</strong>: It registers a custom post type to store talks.</li>
<li><strong>register_settings()</strong>: It registers settings for our plugin.</li>
</ul>
</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Interaction#2: Menu Setup</strong></span></p>
<ul>
<li>The user (in this case Admin) would access our plugin via a WordPress Admin menu. To facilitate this, we would leverage the <strong>admin_menu</strong> action callback implemented by <strong>C9_Wp_Talks_Admin_UI</strong>.</li>
</ul>
<p><span style="text-decoration: underline;"><strong>Interaction#3: Add/Edit Talk<br />
</strong></span></p>
<ul>
<li>When Admin clicks on Add New or Edit Talk, WordPress will take care of showing the edit screen because&#8230; Yes, you guessed it right &#8211; because of the custom post type. However, we do want to show a UI for the additional fields like Presenter Name. To facilitate this, we would leverage the <strong>add_meta_boxes</strong> action callback implemented by <strong>C9_Wp_Talks_Admin_UI</strong>.</li>
</ul>
<p><strong><span style="text-decoration: underline;">Interaction#4: Publish/Update Talk</span><br />
</strong></p>
<ul>
<li>Finally, we are at a point where we can create or save our Talk. Again, WordPress platform will take care of saving the custom post type. We just need to take care of the additional fields. And, for these we will leverage the <strong>save_post_c9_wp_talks_talk</strong> action callback implemented by <strong>C9_Wp_Talks_Admin_Delegate</strong>. Note the name of the hook (<strong>save_post_c9_wp_talks_talk</strong>). This shows the level of details WordPress platform developers have thought through to make it easy for plugin developers. Sweet!</li>
</ul>
<p>How about seeing some actual code now?</p>
<h3>C9_Wp_Talks_Admin_Delegate Code</h3>
<pre class="lang:default decode:true">&lt;?php
/**
 * Class to provide the core admin logic.
 *
 * @since      1.0.0
 * @package    C9_Wp_Talks
 * @subpackage C9_Wp_Talks/includes/code/admin/core
 */
class C9_Wp_Talks_Admin_Delegate {

  /** The logger. */
  private $logger;


  public function __construct($logger) {
    $this-&gt;logger = $logger;
  }

  /** Initialize. */
  public function init() {
    add_action('init', [$this, 'register_cpt']);
    add_action('init', [$this, 'register_settings']);
    add_action(sprintf('save_post_%s', C9_Wp_Talks_Constants::$TALK_POST_TYPE), [$this, 'save_custom_fields']);
    $this-&gt;logger-&gt;debug("C9_Wp_Talks_Admin_Delegate::init(): Initialization completed.");
  }

  /**
   * Registers the custom post type.
   */
  public function register_cpt() {
    $labels = array(
      'name'               =&gt; __('Talks', 'c9-wp-talks'),
      'menu_name'          =&gt; __('Talks', 'c9-wp-talks'),
      'singular_name'      =&gt; __('Talk', 'c9-wp-talks'),
      'all_items'          =&gt; __('All Talks', 'c9-wp-talks'),
      'add_new_item'       =&gt; __('Add New Talk', 'c9-wp-talks'),
      'new_item'           =&gt; __('New Talk', 'c9-wp-talks'),
      'search_items'       =&gt; __('Search Talks', 'c9-wp-talks'),
      'edit_item'          =&gt; __('Edit Talk', 'c9-wp-talks'),
      'not_found'          =&gt; __('No talks found.', 'c9-wp-talks'),
      'not_found_in_trash' =&gt; __('No talks found in Trash.', 'c9-wp-talks')
    );
    $attribs = [
      'labels'              =&gt; $labels,
      'description'         =&gt; __('A custom post type for WordPress talks.', 'c9-wp-talks'),
      'public'              =&gt; false,
      'show_ui'             =&gt; true,
      'has_archive'         =&gt; true,
      'exclude_from_search' =&gt; true,
      'supports'            =&gt; ['title', 'editor', 'author', 'revisions'],
      'show_in_menu'        =&gt; C9_Wp_Talks_Constants::$MENU_SLUG,
      'parent_item'         =&gt; null,
      'menu_icon'           =&gt; null,
      'rewrite'             =&gt; ['slug'  =&gt; C9_Wp_Talks_Constants::$SLUG]
    ];
    $this-&gt;logger-&gt;debug("C9_Wp_Talks_Admin_Delegate::register_cpt(): Registering custom post type...");
    register_post_type(C9_Wp_Talks_Constants::$TALK_POST_TYPE, $attribs);
  }

  /**
   * Registers the settings.
   */
  public function register_settings() {
    $this-&gt;logger-&gt;debug("C9_Wp_Talks_Admin_Delegate::register_settings(): Registering settings...");
    register_setting(C9_Wp_Talks_Constants::$SETTINGS, C9_Wp_Talks_Constants::$DEBUG_MODE_SETTING);
  }

  /**
   * Saves the custom fields after save of the post.
   *
   * @param post_id: The post ID.
   * @param post: The post.
   */
  public function save_custom_fields() {
    global $post;

    wp_verify_nonce(C9_Wp_Talks_Constants::$NONCE_PARAM, C9_Wp_Talks_Constants::$UPDATE_TALK_ACTION);
    if ($post) {
      $post_id = $post-&gt;ID;
      $this-&gt;logger-&gt;debug("C9_Wp_Talks_Admin_Delegate::save_custom_fields(): Saving custom fields...");
      $presenter_name = isset($_POST[C9_Wp_Talks_Constants::$PRESENTER_NAME_FIELD]) ? $_POST[C9_Wp_Talks_Constants::$PRESENTER_NAME_FIELD] : '';
      $presenter_website = isset($_POST[C9_Wp_Talks_Constants::$PRESENTER_WEBSITE_FIELD]) ? $_POST[C9_Wp_Talks_Constants::$PRESENTER_WEBSITE_FIELD] : '';
      $recording_url = isset($_POST[C9_Wp_Talks_Constants::$RECORDING_URL_FIELD]) ? $_POST[C9_Wp_Talks_Constants::$RECORDING_URL_FIELD] : '';
      $this-&gt;logger-&gt;debug("C9_Wp_Talks_Admin_Delegate::save_custom_fields(): Presenter name: $presenter_name, website: $presenter_website, recording_url: $recording_url");
  
      // Save fields now
      update_post_meta($post_id, C9_Wp_Talks_Constants::$PRESENTER_NAME_FIELD, $presenter_name);
      update_post_meta($post_id, C9_Wp_Talks_Constants::$PRESENTER_WEBSITE_FIELD, $presenter_website);
      update_post_meta($post_id, C9_Wp_Talks_Constants::$RECORDING_URL_FIELD, $recording_url);
    }
  }
}
</pre>
<p><strong>C9_Wp_Talks_Admin_Delegate</strong> provides the core admin logic.<strong><br />
</strong></p>
<ul>
<li>The <strong>init()</strong> method registers callbacks for the required hooks so that the WordPress platform can invoke these at appropriate time.</li>
<li>The <strong>register_cpt()</strong> callback registers the <strong>c9_wp_talks_talk </strong>custom post type. Once registered, this type will be available for subsequent usage.</li>
<li>The <strong>register_settings()</strong> callback registers the debug mode setting. The idea being when the setting is on debug messages will be printed to the WordPress <strong>debug.log</strong> file. This is helpful for troubleshooting. When done, turn off the debug mode.</li>
<li>Lastly, the <strong>save_custom_fields()</strong> callback is invoked after a talk is saved. In this method, we take care of saving the additional attributes &#8211; Presenter Name, Presenter Website and Recording URL.
<ul>
<li>Note the use of <a href="https://codex.wordpress.org/WordPress_Nonces">nonce</a> (number used once). A nonce is a measure to prevent malicious security attacks by generating a unique string that is only valid for a limited time (typically, in WordPress for 24hours). WordPress offers convenient methods to generate and verify nonce.</li>
</ul>
</li>
</ul>
<h3>C9_Wp_Talks_Admin_UI Code</h3>
<pre class="lang:default decode:true">&lt;?php
/**
 * Class to provide the admin UI logic.
 *
 * @since      1.0.0
 * @package    C9_Wp_Talks
 * @subpackage C9_Wp_Talks/includes/code/admin/ui
 */
class C9_Wp_Talks_Admin_UI {

  /** The logger. */
  private $logger;

  /** The delegate. */
  private $delegate;


  public function __construct($logger, $delegate) {
    $this-&gt;logger = $logger;
    $this-&gt;delegate = $delegate;
  }

  /** Initialize. */
  public function init() {
    add_action('admin_menu', [$this, 'register_menu']);
    add_action('add_meta_boxes', [$this, 'add_presenter_info_meta_box']);
    $this-&gt;logger-&gt;debug("C9_Wp_Talks_Admin_UI::init(): Initialization completed.");
  }

  /**
   * Registers the menu.
   */
  public function register_menu() {
    $menu_slug = C9_Wp_Talks_Constants::$MENU_SLUG;
    add_menu_page(__('Talks', 'c9-wp-talks'), __('Talks', 'c9-wp-talks'), 'manage_options', $menu_slug, '', 'dashicons-welcome-view-site');
    add_submenu_page($menu_slug, __('Settings', 'c9-wp-talks'), __('Settings', 'c9-wp-talks'), 'manage_options', C9_Wp_Talks_Constants::$SETTINGS_PAGE, [$this, 'show_settings_page']);
  }

  /**
   * Shows the settings page.
   */
  public function show_settings_page() {
    if ( !current_user_can( 'manage_options' ) )  {
      wp_die(__('You do not have sufficient permissions to access this page.'));
    }
?&gt;
&lt;div class="wrap"&gt;
  &lt;h1&gt;&lt;?php _e('C9 WordPress Talks Settings', 'c9-wp-talks'); ?&gt;&lt;/h1&gt;
  &lt;?php settings_errors(); ?&gt;
  &lt;h2 class="nav-tab-wrapper"&gt;
    &lt;a href="#" class="nav-tab nav-tab-active"&gt;&lt;?php _e('General', 'c9-wp-talks'); ?&gt;&lt;/a&gt;
  &lt;/h2&gt;
  &lt;form method="post" action="options.php"&gt;
    &lt;?php settings_fields(C9_Wp_Talks_Constants::$SETTINGS); ?&gt;
    &lt;?php do_settings_sections(C9_Wp_Talks_Constants::$SETTINGS); ?&gt;
    &lt;table&gt;
      &lt;tr&gt;
        &lt;td colspan="2"&gt;&amp;nbsp;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;?php $this-&gt;show_settings_fields(); ?&gt;
      &lt;tr&gt;
        &lt;td colspan="2" align="center"&gt;&lt;?php submit_button(); ?&gt;&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/table&gt;
  &lt;/form&gt;
&lt;/div&gt;
&lt;?php
  }
    
  /**
   * Shows settings fields.
   */
  public function show_settings_fields() {
?&gt;
      &lt;tr&gt;
        &lt;th&gt;&lt;?php _e('Enable Debug Mode', 'c9-wp-talks'); ?&gt;&lt;/th&gt;
        &lt;td&gt;&lt;input type="checkbox" name="&lt;?php echo C9_Wp_Talks_Constants::$DEBUG_MODE_SETTING; ?&gt;" value="true" &lt;?php echo esc_attr(get_option(C9_Wp_Talks_Constants::$DEBUG_MODE_SETTING, C9_Wp_Talks_Constants::$DEBUG_MODE_SETTING_DEFAULT)) == 'true' ? 'checked="checked"' : ''; ?&gt;/&gt;&lt;/td&gt;
      &lt;/tr&gt;
&lt;?php
  }

  /** Adds the presenter information meta box. */
  public function add_presenter_info_meta_box() {
    add_meta_box(C9_Wp_Talks_Constants::$ADDITIONAL_DATA_META_BOX_ID, __('Presenter Information', 'c9-wp-talks'), [$this, 'add_presenter_info_meta_box_content'], C9_Wp_Talks_Constants::$TALK_POST_TYPE, 'side');
  }
    
  /** Adds the presenter information meta box content. */
  public function add_presenter_info_meta_box_content() {
    global $post;
        
    // Add the security field
    wp_nonce_field(C9_Wp_Talks_Constants::$UPDATE_TALK_ACTION, C9_Wp_Talks_Constants::$NONCE_PARAM);
    // meta data fields
    $presenter_name = get_post_meta($post-&gt;ID, C9_Wp_Talks_Constants::$PRESENTER_NAME_FIELD, true);
    $presenter_website = get_post_meta($post-&gt;ID, C9_Wp_Talks_Constants::$PRESENTER_WEBSITE_FIELD, true);
    $recording_url = get_post_meta($post-&gt;ID, C9_Wp_Talks_Constants::$RECORDING_URL_FIELD, true);
    $this-&gt;logger-&gt;debug("C9_Wp_Talks_Admin_UI::add_presenter_info_meta_box_content(): Presenter name: $presenter_name, website: $presenter_websit, recording_url: $recording_urle");
?&gt;
&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;&lt;?php _e('Name', 'c9-wp-talks'); ?&gt;&lt;/th&gt;
    &lt;td&gt;
      &lt;input type="text" id="&lt;?php echo C9_Wp_Talks_Constants::$PRESENTER_NAME_FIELD; ?&gt;" name="&lt;?php echo C9_Wp_Talks_Constants::$PRESENTER_NAME_FIELD; ?&gt;" value="&lt;?php echo esc_attr($presenter_name); ?&gt;" size="15"/&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;&lt;?php _e('Website', 'c9-wp-talks'); ?&gt;&lt;/th&gt;
    &lt;td&gt;
      &lt;input type="text" id="&lt;?php echo C9_Wp_Talks_Constants::$PRESENTER_WEBSITE_FIELD; ?&gt;" name="&lt;?php echo C9_Wp_Talks_Constants::$PRESENTER_WEBSITE_FIELD; ?&gt;" value="&lt;?php echo esc_attr($presenter_website); ?&gt;" size="15"/&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;&lt;?php _e('Recording URL', 'c9-wp-talks'); ?&gt;&lt;/th&gt;
    &lt;td&gt;
      &lt;input type="text" id="&lt;?php echo C9_Wp_Talks_Constants::$RECORDING_URL_FIELD; ?&gt;" name="&lt;?php echo C9_Wp_Talks_Constants::$RECORDING_URL_FIELD; ?&gt;" value="&lt;?php echo esc_attr($recording_url); ?&gt;" size="15"/&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
&lt;?php
  }
}
</pre>
<p><strong>C9_Wp_Talks_Admin_UI</strong> provides the core logic for the admin UI.</p>
<ul>
<li>Again, the <strong>init()</strong> method registers callbacks for the required hooks.</li>
<li>The <strong>register_menu()</strong> callback shows a <strong>Talks</strong> menu (shown in the admin sidebar). In addition, it also adds a sub-menu item for the Settings page.
<ul>
<li>The <strong>show_settings_page()</strong> method shows the settings page with the debug mode setting using the <strong>show_settings_fields()</strong> method. Note how it uses the out-of-the-box methods like <strong>settings_errors()</strong> to display messages as opposed to writing code specifically for this.</li>
</ul>
</li>
<li>The <strong>add_presenter_info_metabox()</strong> callback shows the Presenter Information fields in the sidebar when a Talk is being edited. Note the use of <strong>wp_nonce_field()</strong> method to generate a nonce field that will be verified at the backend.</li>
</ul>
<h3>C9_Wp_Talks_Public_Delegate Code</h3>
<pre class="lang:default decode:true">&lt;?php
/**
 * Class to provide the core public logic.
 *
 * @since      1.0.0
 * @package    C9_Wp_Talks
 * @subpackage C9_Wp_Talks/includes/code/public/core
 */
class C9_Wp_Talks_Public_Delegate {

  /** The logger. */
  private $logger;


  public function __construct($logger) {
    $this-&gt;logger = $logger;
  }

  /** Initialize. */
  public function init() {
    add_shortcode(C9_Wp_Talks_Constants::$INSERT_TALKS_SHORTCODE, [$this, 'get_talks']);
    add_shortcode(C9_Wp_Talks_Constants::$INSERT_TALK_SHORTCODE, [$this, 'get_talk']);
    $this-&gt;logger-&gt;debug("C9_Wp_Talks_Public_Delegate::init(): Initialization completed.");
  }

  /**
   * Returns the talks.
   *
   * @param attribs: The shortcode attributes.
   * @param content: The shortcode content.
   */
  public function get_talks($attribs=[], $content=null) {
    $id_header = __('ID', 'c9-wp-talks');
    $title_header = __('Title', 'c9-wp-talks');
    $out = &lt;&lt;&lt;EOL
&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;$id_header&lt;/th&gt;
    &lt;th&gt;$title_header&lt;/th&gt;
  &lt;/tr&gt;
EOL;
    $results = new WP_Query([C9_Wp_Talks_Constants::$POST_TYPE_FIELD =&gt; C9_Wp_Talks_Constants::$TALK_POST_TYPE]);
    if ($results-&gt;have_posts()) {
      $talks = $results-&gt;posts;
      foreach ($talks as $talk) {
        $id = $talk-&gt;ID;
        $title = $talk-&gt;post_title;
        $out .= &lt;&lt;&lt;EOL
  &lt;tr&gt;
    &lt;td&gt;$id&lt;/td&gt;
    &lt;td&gt;$title&lt;/td&gt;
  &lt;/tr&gt;
EOL;
      }
            
      // Clean up
      wp_reset_postdata();
    } // if (talks found)
    else {
      $out .= &lt;&lt;&lt;EOL
  &lt;tr&gt;
    &lt;td colspan='2'&gt;&lt;?php _e('No talks found.', 'c9-wp-talks'); ?&gt;&lt;/td&gt;
  &lt;/tr&gt;
EOL;
    }
    $out .= &lt;&lt;&lt;EOL
&lt;/table&gt;
EOL;
    return $out;
  }

  /**
   * Returns the talk with the specified ID.
   *
   * @param attribs: The shortcode attributes.
   * @param content: The shortcode content.
   */
  public function get_talk($attribs=[], $content=null) {
    $out = "";
    if (isset($attribs[C9_Wp_Talks_Constants::$ID_ATTRIB])) {
      $id = $attribs[C9_Wp_Talks_Constants::$ID_ATTRIB];
      $talk = get_post($id);
      if ($talk) {
        $title = $talk-&gt;post_title;
        $description = $talk-&gt;post_content;
        $presenter_name = get_post_meta($id, C9_Wp_Talks_Constants::$PRESENTER_NAME_FIELD, true);
        $presenter_website = get_post_meta($id, C9_Wp_Talks_Constants::$PRESENTER_WEBSITE_FIELD, true);
        $recording_url = get_post_meta($id, C9_Wp_Talks_Constants::$RECORDING_URL_FIELD, true);
        $out = &lt;&lt;&lt;EOL
&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;Title:&lt;/th&gt;
    &lt;td&gt;&lt;strong&gt;$title&lt;/strong&gt;&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;Presenter Name:&lt;/th&gt;
    &lt;td&gt;$presenter_name&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;Presenter Website:&lt;/th&gt;
    &lt;td&gt;$presenter_website&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;th&gt;Recording URL:&lt;/th&gt;
    &lt;td&gt;&lt;a href='$recording_url' target='_blank'&gt;$recording_url&lt;/a&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
EOL;
      }
    }

    return $out;
  }
}</pre>
<p><strong>C9_Wp_Talks_Public_Delegate</strong> provides the core logic for the public.</p>
<ul>
<li>The <strong>init()</strong> method registers the following <strong>shortcodes</strong>.
<ul>
<li><strong>c9-wpt-insert-talks</strong>: A shortcode to embed a list of talks.</li>
<li><strong>c9-wpt-insert-talk</strong>: A shortcode to embed information about a specific task by providing it&#8217;s ID.</li>
</ul>
</li>
<li>The <strong>get_talks()</strong> method provides the logic to retrieve all talks.
<ul>
<li>It uses <strong>WP_Query</strong> to retrieve all objects of custom post type <strong>c9_wp_talks_talk</strong>. You can update this query to use pagination especially if there are a lot of talks.</li>
<li>It iterates through the results and prepares an HTML formatted output.</li>
<li>Finally, it cleans up any opened resources to ensure no data leakage happens.</li>
</ul>
</li>
<li>Similarly, the <strong>get_talk()</strong> method retrieves information about the specified talk using the <strong>get_post()</strong> method. It formats the output as HTML and returns it.</li>
</ul>
<h3>C9_Wp_Talks Changes</h3>
<p><span style="text-decoration: underline;">Note</span>: Following code shows updated snippets only.</p>
<pre class="lang:default decode:true">  /**
   * Register all of the hooks related to the admin area functionality
   * of the plugin.
   *
   * @since    1.0.0
   * @access   private
   */
  private function define_admin_hooks() {
    $debug_enabled = get_option(C9_Wp_Talks_Constants::$DEBUG_MODE_SETTING, C9_Wp_Talks_Constants::$DEBUG_MODE_SETTING_DEFAULT);
    $logger = new C9_Log_Writer($debug_enabled);
    $delegate = new C9_Wp_Talks_Admin_Delegate($logger);
    $ui = new C9_Wp_Talks_Admin_UI($logger, $delegate);
    $plugin_admin = new C9_Wp_Talks_Admin( $this-&gt;get_plugin_name(), $this-&gt;get_version() );

    // Initialize
    $delegate-&gt;init();
    $ui-&gt;init();

    $this-&gt;loader-&gt;add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
    $this-&gt;loader-&gt;add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
  }

  /**
   * Register all of the hooks related to the public-facing functionality
   * of the plugin.
   *
   * @since    1.0.0
   * @access   private
   */
  private function define_public_hooks() {
    $debug_enabled = get_option(C9_Wp_Talks_Constants::$DEBUG_MODE_SETTING, C9_Wp_Talks_Constants::$DEBUG_MODE_SETTING_DEFAULT);
    $logger = new C9_Log_Writer($debug_enabled);
    $delegate = new C9_Wp_Talks_Public_Delegate($logger);
    $plugin_public = new C9_Wp_Talks_Public( $this-&gt;get_plugin_name(), $this-&gt;get_version() );

    // Initialize
    $delegate-&gt;init();

    $this-&gt;loader-&gt;add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_styles' );
    $this-&gt;loader-&gt;add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_scripts' );
  }</pre>
<p>Now that we have our custom classes ready, it is time to hook these up in the generated skeleton code so that the WordPress platform can start interacting with these. This is done in the <strong>C9_Wp_Talks</strong> class.</p>
<ul>
<li>Update the <strong>load_dependencies()</strong> method to load the custom classes.</li>
<li>The <strong>define_admin_hooks()</strong> method is updated to create the admin delegate and UI objects and to call their respective <strong>init()</strong> methods.</li>
<li>The <strong>define_public_hooks()</strong> method is updated to create the public delegate and to call it&#8217;s <strong>init()</strong> method.</li>
</ul>
<h3>Let&#8217;s see our plugin in action</h3>
<p>Our plugin is ready to roll! Here is a screenshot of a simple page that uses our plugin shortcodes.</p>
<p><a href="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?ssl=1"><img class="alignnone wp-image-1106 size-medium" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=300%2C213&#038;ssl=1" alt="C9 WordPress Talks - Shortcodes Demo Page" width="300" height="213" srcset="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=300%2C213&amp;ssl=1 300w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=768%2C546&amp;ssl=1 768w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=1024%2C728&amp;ssl=1 1024w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=320%2C228&amp;ssl=1 320w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=640%2C455&amp;ssl=1 640w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=360%2C256&amp;ssl=1 360w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=720%2C512&amp;ssl=1 720w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=1080%2C768&amp;ssl=1 1080w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=800%2C569&amp;ssl=1 800w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?resize=1280%2C910&amp;ssl=1 1280w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo_Page.png?w=1294&amp;ssl=1 1294w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></p>
<p>And here is the output of the page.</p>
<p><a href="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?ssl=1"><img class="alignnone size-medium wp-image-1105" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=300%2C153&#038;ssl=1" alt="WordPress Talks - Shortcodes Demo" width="300" height="153" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=300%2C153&amp;ssl=1 300w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=768%2C391&amp;ssl=1 768w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=1024%2C521&amp;ssl=1 1024w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=320%2C163&amp;ssl=1 320w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=640%2C326&amp;ssl=1 640w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=360%2C183&amp;ssl=1 360w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=720%2C367&amp;ssl=1 720w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=1080%2C550&amp;ssl=1 1080w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=800%2C407&amp;ssl=1 800w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?resize=1280%2C652&amp;ssl=1 1280w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/C9_Wp_Talks_Shortcodes_Demo.png?w=1630&amp;ssl=1 1630w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></p>
<p><span style="color: #339966;"><strong>Hurray! We can see our plugin in action.</strong></span></p>
<h3><strong>Unit Testing Your Plugin</strong></h3>
<p>For Unit Testing, we will leverage WordPress itself! So, these tests will simulate closely how your code will run in an actual WordPress installation.</p>
<h4>Unit Testing Setup</h4>
<ul>
<li>Install PHPUnit.<br />
<a href="https://phpunit.de/">https://phpunit.de/</a></li>
<li>Install the WordPress CLI.<br />
<a href="https://wp-cli.org/">https://wp-cli.org/</a></li>
<li>Create an empty WordPress installation for our tests.
<pre class="lang:sh decode:true">bin/install-wp-tests.sh cnapps_wp_test &lt;dbadmin&gt; &lt;password&gt; localhost latest</pre>
<p>This does 2 main things.</p>
<ul>
<li>Downloads the latest WordPress release and installs in a temporary directory.</li>
<li>Creates a database for this Unit Testing WordPress setup. This database creation is needed one time only.</li>
</ul>
</li>
<li>Initialize the test setup. This creates the unit test related files and a sample unit test file.
<pre class="lang:sh decode:true " title="WPTestSetup">wp scaffold plugin-tests c9-wp-talks</pre>
</li>
<li>Update the <strong>phpunit.xml.dist</strong> so that code coverage is generated correctly. Otherwise, when you run unit tests, you will likely note an error about incorrect whitelist config.
<pre class="lang:default decode:true">&lt;?xml version="1.0"?&gt;
&lt;phpunit
  bootstrap="tests/bootstrap.php"
  backupGlobals="false"
  colors="true"
  convertErrorsToExceptions="true"
  convertNoticesToExceptions="true"
  convertWarningsToExceptions="true"
  &gt;
  &lt;filter&gt;
    &lt;whitelist&gt;
      &lt;directory suffix=".php"&gt;./&lt;/directory&gt;
      &lt;exclude&gt;
        &lt;directory suffix=".php"&gt;./tests&lt;/directory&gt;
      &lt;/exclude&gt;
    &lt;/whitelist&gt;
  &lt;/filter&gt;
  &lt;logging&gt;
    &lt;log type="coverage-text" target="php://stdout" showUncoveredFiles="false"/&gt;
    &lt;log type="coverage-html" target="coverage/report"/&gt;
  &lt;/logging&gt;
  &lt;testsuites&gt;
    &lt;testsuite&gt;
      &lt;directory prefix="test-" suffix=".php"&gt;./tests/&lt;/directory&gt;
    &lt;/testsuite&gt;
  &lt;/testsuites&gt;
&lt;/phpunit&gt;
</pre>
</li>
<li>You should now be able to check your setup is ready by running the following command.
<pre class="lang:sh decode:true ">phpunit</pre>
<p><a href="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?ssl=1"><img class="alignnone size-medium wp-image-1087" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=300%2C174&#038;ssl=1" alt="" width="300" height="174" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=300%2C174&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=768%2C446&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=1024%2C595&amp;ssl=1 1024w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=320%2C186&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=640%2C372&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=360%2C209&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=720%2C419&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=1080%2C628&amp;ssl=1 1080w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?resize=800%2C465&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/WordPress/Writing_First_WordPress_Plugin/Initial_UT_Run.png?w=1132&amp;ssl=1 1132w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></p>
</li>
</ul>
<h3>Let&#8217;s add real Unit Tests</h3>
<p>Now that we have our unit test setup working, lets add a couple real unit tests. Here&#8217;s the code.</p>
<pre class="lang:default decode:true">&lt;?php
/**
 * C9_Wp_Talks_Admin Unit Tests.
 *
 * @package C9_Wp_Talks
 */

/**
 * C9_Wp_Talks_Admin Unit Tests.
 */
class C9_Wp_Talks_Admin_Test extends WP_UnitTestCase {

  /** Initializes the test. */
  public function setUp() {
    parent::setUp();
    $this-&gt;admin_user_id = $this-&gt;factory-&gt;user-&gt;create(['role' =&gt; 'admin']);
    wp_set_current_user($this-&gt;admin_user_id);
  }

  /** Clean up. */
  public function tearDown() {
    parent::tearDown();
  }

  /** Tests successful creation of a talk. */
  public function test_plugin_loaded_success() {
    // Validate
    $this-&gt;assertTrue(class_exists('C9_Wp_Talks'), "Main plugin class 'C9_Wp_Talks' not found.");
  }

  /** Tests successful creation of a talk. */
  public function test_create_talk_success() {
    // Initialize
    $presenter_name = 'Nitin Patil';
    $presenter_website = 'https://cloudnineapps.com';
    $recording_url = 'https://cloudnineapps.com/';

    // Execute
    $talk = $this-&gt;factory-&gt;post-&gt;create_and_get([
      'post_type'    =&gt; C9_Wp_Talks_Constants::$TALK_POST_TYPE,
      'post_title'   =&gt; $this-&gt;getName() . ' - Talk',
      'post_content' =&gt; $this-&gt;getName() . ' - Content'
    ]);
    update_post_meta($talk-&gt;ID, C9_Wp_Talks_Constants::$PRESENTER_NAME_FIELD, $presenter_name);
    update_post_meta($talk-&gt;ID, C9_Wp_Talks_Constants::$PRESENTER_WEBSITE_FIELD, $presenter_website);
    update_post_meta($talk-&gt;ID, C9_Wp_Talks_Constants::$RECORDING_URL_FIELD, $recording_url);

    // Validate
    $this-&gt;assertTrue($talk-&gt;ID &gt; 0, "Talk did not get created successfully.");
    $fetched_presenter_name = get_post_meta($talk-&gt;ID, C9_Wp_Talks_Constants::$PRESENTER_NAME_FIELD, $presenter_name);
    $fetched_presenter_website = get_post_meta($talk-&gt;ID, C9_Wp_Talks_Constants::$PRESENTER_WEBSITE_FIELD, $presenter_website);
    $fetched_recording_url = get_post_meta($talk-&gt;ID, C9_Wp_Talks_Constants::$RECORDING_URL_FIELD, $recording_url);
    $this-&gt;assertEquals($presenter_name, $fetched_presenter_name, "Incorrect presenter name.");
    $this-&gt;assertEquals($presenter_website, $fetched_presenter_website, "Incorrect presenter website.");
    $this-&gt;assertEquals($recording_url, $fetched_recording_url, "Incorrect recording url.");
  }
}
</pre>
<p>Let&#8217;s review the key points.</p>
<ul>
<li>The test class extends from <strong>WP_UnitTestCase</strong>, which provides a set of convenience methods, such as, factory methods to create test post objects, etc.</li>
<li>The <strong>setUp()</strong> and <strong>tearDown()</strong> methods perform the common unit testing behavior &#8211; per test set up and clean up, respectively. You should use these to leverage any common initialization and clean up code.</li>
<li>The <strong>test_plugin_loaded_success()</strong> method shows a quick way to check whether our plugin is loaded successfully by checking existence of the main plugin class.</li>
<li>The <strong>test_create_talk_success()</strong> method tests successful creation of a talk object.
<ul>
<li>It first creates a task object using the factory method &#8211; <strong>create_and_get()</strong>. Note the use of the <strong>custom post type</strong>.</li>
<li>It then sets the additional attributes just like a real user would when using our plugin.</li>
<li>Finally, it validates the talk got persisted successfully and validates the meta data indeed got associated with the talk.</li>
</ul>
</li>
</ul>
<p>This is to give an idea. You can certainly write more functional unit tests for various scenarios including some negative testing scenarios.</p>
<div class="su-note"  style="border-color:#e5e5b2;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#FFFFCC;border-color:#ffffff;color:#333333;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;">I recommend using the actual scenarios for test names and appending a string like &#8216;_success&#8217; to indicate this is a happy path/normal scenario.</div></div>
<h2>Resources</h2>
<p>All the source code for the plugin including unit tests is available at the following GIT repository.</p>
<p><a href="https://github.com/nitinc9/c9-wp-talks">https://github.com/nitinc9/c9-wp-talks</a></p>
<p>Happy developing!<br />
&#8211; Nitin</p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Build smart reusable content that is easy to maintain.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/"><img class="wp-image-728 size-full aligncenter" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-small.png?resize=128%2C128&#038;ssl=1" alt="" width="128" height="128" data-recalc-dims="1" /></a></p>
<center><strong><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/">C9 Variables</a> (FREE)</strong></center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/"><img class="wp-image-663 size-full aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables-pro/c9-variables-pro-small.png?resize=128%2C128&#038;ssl=1" alt="" width="128" height="128" data-recalc-dims="1" /></a></p>
<center><strong><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/">C9 Variables Pro</a></strong></center>
<p></div></div> </div></div></div></p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwriting-your-first-wordpress-plugin%2F&amp;linkname=Writing%20Your%20First%20WordPress%20Plugin" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwriting-your-first-wordpress-plugin%2F&amp;linkname=Writing%20Your%20First%20WordPress%20Plugin" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwriting-your-first-wordpress-plugin%2F&amp;linkname=Writing%20Your%20First%20WordPress%20Plugin" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwriting-your-first-wordpress-plugin%2F&amp;linkname=Writing%20Your%20First%20WordPress%20Plugin" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwriting-your-first-wordpress-plugin%2F&#038;title=Writing%20Your%20First%20WordPress%20Plugin" data-a2a-url="https://cloudnineapps.com/blogs/wordpress/writing-your-first-wordpress-plugin/" data-a2a-title="Writing Your First WordPress Plugin"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/writing-your-first-wordpress-plugin/">Writing Your First WordPress Plugin</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/wordpress/writing-your-first-wordpress-plugin/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1050</post-id>	</item>
		<item>
		<title>C9 Variables and C9 Variables Pro V1.0.0 Release</title>
		<link>https://cloudnineapps.com/blogs/wordpress/announcing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins/</link>
					<comments>https://cloudnineapps.com/blogs/wordpress/announcing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Thu, 26 Apr 2018 01:23:11 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=901</guid>

					<description><![CDATA[<p>C9 Variables and C9 Variables Pro V1.0.0 Release Content makes the Internet click. As content authors we all strive to offer the best to our end users, to keep it interesting and useful. But, let&#8217;s face it. Content Management is&#8230;&#160;<a href="https://cloudnineapps.com/blogs/wordpress/announcing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/announcing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins/">C9 Variables and C9 Variables Pro V1.0.0 Release</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>C9 Variables and C9 Variables Pro V1.0.0 Release</h1>
<p>Content makes the Internet click. As content authors we all strive to offer the best to our end users, to keep it interesting and useful. But, let&#8217;s face it. Content Management is a challenge. Often we end up duplicating content in many places and then hustle to keep it updated. Not an easy task. What if we could modularize content in a way that&#8217;s reusable and easy to maintain? Sounds like a dream? Well, it&#8217;s about to come true now. Our latest release of Content Management WordPress plugins &#8211; <a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/">C9 Variables</a> and <a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/">C9 Variables Pro</a> makes it easy to manage reusable smart content so that you can use your time for more important things &#8211; building interesting and useful content for your end users.</p>
<div class="su-box su-box-style-default" id="" style="border-color:#c74d3f;border-radius:5px"><div class="su-box-title" style="background-color:#FA8072;color:#454545;border-top-left-radius:3px;border-top-right-radius:3px">Announcing launch of C9 Variables and C9 Variables Pro</div><div class="su-box-content su-u-clearfix su-u-trim" style="border-bottom-left-radius:3px;border-bottom-right-radius:3px"> <div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim">
<h3><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables">C9 Variables</a> (Free)</h3>
<div class="alignleft"><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables"><img class="alignnone wp-image-728 size-full" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-small.png?resize=128%2C128&#038;ssl=1" alt="C9 Variables" width="128" height="128" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-small.png?w=128&amp;ssl=1 128w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-small.png?resize=100%2C100&amp;ssl=1 100w" sizes="(max-width: 128px) 100vw, 128px" data-recalc-dims="1" /></a></div>
<p><i>Use variables to make smart reusable content. Whether you are a webmaster, web developer or a content editor, it is crucial to author content in an efficient manner. <strong>C9 Variables</strong> makes it easy to build modular content that can be reused and managed efficiently.</i><br />
<a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables">Check it out</a> now. </div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim">
<h3><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro">C9 Variables Pro</a> (Paid)</h3>
<div class="alignleft"><a href="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables-pro/c9-variables-pro-small.png?ssl=1"><img class="alignnone size-full wp-image-663" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables-pro/c9-variables-pro-small.png?resize=128%2C128&#038;ssl=1" alt="" width="128" height="128" srcset="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables-pro/c9-variables-pro-small.png?w=128&amp;ssl=1 128w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables-pro/c9-variables-pro-small.png?resize=100%2C100&amp;ssl=1 100w" sizes="(max-width: 128px) 100vw, 128px" data-recalc-dims="1" /></a></div>
<p><i>The Pro plugin makes content management even more simple and fun! It provides all the capabilities of <strong>C9 Variables</strong> and much more. Mark favorites and customize variable lookup order. Who says content editing cannot be fun?</i><br />
<a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro">Check it out</a> now. </div></div> </div> </div></div>
<h2>Some Usecases</h2>
<p>Lets put things in perspective. Here are some examples of content reuse where these plugins can be useful.</p>
<ul>
<li>Repeating common content, such as, product features across multiple content on your site, such as, blog posts, product pages, etc. (<a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/c9-variables-demo/#product_features" target="_blank" rel="noopener">See Demo</a>)</li>
<li>Content like promotion code that keeps changing and you want to make sure the links always use correct and latest codes. (<a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/c9-variables-demo/#promo_code" target="_blank" rel="noopener">See Demo</a>)</li>
</ul>
<p>There are also other interesting scenarios for using <strong>Variables</strong>.</p>
<ul>
<li>Content promotion scenarios, where things like link URLs change, but rest of the content remains the same. Example, promoting content from development or staging to production. (<a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/c9-variables-demo/#site" target="_blank" rel="noopener">See Demo</a>)</li>
<li>Likewise content that needs to be kept ready in production but not made live until the release date. Yes, sort of like a magic button! (<a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/c9-variables-demo/#magic_button" target="_blank" rel="noopener">See Demo</a>)</li>
</ul>
<p>As you can imagine, this list can be quite huge in reality because content can be authored in many different ways.</p>
<h2>Features</h2>
<p>A case in point is this post itself where I will show you the features supported by these plugins. But, instead of repeating the content, we will simply reuse &#8211; you guessed it right, the contents from the product pages. These contents have been organized into Variables.</p>
<h3>C9 Variables Features</h3>
<ul>
	<li>WordPress Admin

<ul>
	<li>Add/modify/delete up to 10 Variables</li>
	<li>Support for WordPress built-in roles: Super Admin, Administrator, Editor, Author, Contributor, Subscriber (<a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/documentation/#roles_and_capabilities" target="_blank" rel="noopener">see details</a>)</li>
	<li>Page/Post Editor Enhancements

<ul>
	<li>Integrated Editor button to lookup and insert a Variable</li>
	<li>Organize Variable list by title</li>
	<li>Use selected Variable in the post/page via a convenient shortcode</li>
</ul>
</li>
	<li>Settings

<ul>
	<li>Debug Mode: On/Off (default: Off)</li>
	<li>Anonymous Usage Tracking: On/Off (default: Off)</li>
</ul>
</li>
</ul>
</li>
	<li>WordPress Public

<ul>
	<li>Replace Variable value when showing the post/page</li>
</ul>
</li>
</ul>
<h3>C9 Variables Pro Features</h3>
<ul>
	<li>WordPress Admin

<ul>
	<li>Unlimited Variables</li>
	<li>Mark favorite Variables</li>
	<li>Page/Post Editor Enhancements

<ul>
	<li>Variable lookup supports searching by favorites</li>
	<li>Variable lookup supports sorting results by Last Used or Title</li>
	<li>Variable lookup supports pagination and configurable page size</li>
</ul>
</li>
	<li>Settings

<ul>
	<li>Default Variable Sort Order: Title, Last Used (default: Title)</li>
	<li>Number of Results per Page: 10, 25, 50 (default: 10)</li>
</ul>
</li>
</ul>
</li>
</ul>
<div> </div>
<p>And, this is just the beginning! We will continue to add more productivity improvement features and hope that you find these plugins useful.</p>
<p>Happy authoring!<br />
&#8211; Nitin</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fannouncing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins%2F&amp;linkname=C9%20Variables%20and%20C9%20Variables%20Pro%20V1.0.0%20Release" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fannouncing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins%2F&amp;linkname=C9%20Variables%20and%20C9%20Variables%20Pro%20V1.0.0%20Release" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fannouncing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins%2F&amp;linkname=C9%20Variables%20and%20C9%20Variables%20Pro%20V1.0.0%20Release" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fannouncing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins%2F&amp;linkname=C9%20Variables%20and%20C9%20Variables%20Pro%20V1.0.0%20Release" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fannouncing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins%2F&#038;title=C9%20Variables%20and%20C9%20Variables%20Pro%20V1.0.0%20Release" data-a2a-url="https://cloudnineapps.com/blogs/wordpress/announcing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins/" data-a2a-title="C9 Variables and C9 Variables Pro V1.0.0 Release"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/announcing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins/">C9 Variables and C9 Variables Pro V1.0.0 Release</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/wordpress/announcing-v1-0-0-release-of-c9-variables-and-c9-variables-pro-plugins/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">901</post-id>	</item>
		<item>
		<title>Getting Started With WordPress for Developers</title>
		<link>https://cloudnineapps.com/blogs/wordpress/getting-started-wordpress-developers-webmasters/</link>
					<comments>https://cloudnineapps.com/blogs/wordpress/getting-started-wordpress-developers-webmasters/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Sun, 04 Mar 2018 05:02:25 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[wordpress tutorial]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=495</guid>

					<description><![CDATA[<p>Getting Started With WordPress for Developers and Webmasters Introduction As I embarked on my journey with WordPress, I came across several great resources on the Net that covered different aspects of the WordPress setup. It is quite evident that it&#8217;s&#8230;&#160;<a href="https://cloudnineapps.com/blogs/wordpress/getting-started-wordpress-developers-webmasters/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/getting-started-wordpress-developers-webmasters/">Getting Started With WordPress for Developers</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Getting Started With WordPress for Developers and Webmasters</h1>
<h2>Introduction</h2>
<p>As I embarked on <a href="https://cloudnineapps.com/blogs/wordpress/wordpress-journey-begun/">my journey with WordPress</a>, I came across several great resources on the Net that covered different aspects of the WordPress setup. It is quite evident that it&#8217;s not just a great platform, but it also has an equally vibrant community backing it. In this post/tutorial, I will try to summarize what you need to get your first WordPress site rolling from soup to nuts, esp. if you have some development or webmaster background. And, what I mean by that is you are comfortable with things like installing typical development tools, manipulating basic PHP code or simple database configuration. Lastly, while this post is primarily geared towards developers and webmasters, regular users or at times even WordPress veterans may find something useful as I try to bring in some general development best practices.</p>
<p><span style="text-decoration: underline;">Note</span>: As it is well known, WordPress along with it&#8217;s overall eco-system has a huge set of capabilities, there are at times different ways of accomplishing the same results. This post covers what I figured out over past few months and hopefully it is useful to you. But, certainly do not be limited by what I cover here. As WordPress is continuously evolving, you may find better ways. And, if you do come across something, please feel free to share in the comments.</p>
<h2><strong>First things first: I</strong>dentify your website goals</h2>
<p>It is business 101. Identify what are you trying to accomplish with the site? Even if you are just setting it up for fun, put down a few goals. And, I&#8217;ll tell you why this is so important.</p>
<ul>
<li>If you&#8217;ve played with WordPress even a little bit, it&#8217;s plugins and themes, you perhaps already know that it&#8217;s like an ocean out there. So, unless you know what type of things you want to accomplish, it is very easy to get lost.</li>
<li>Identifying a few key goals will help you get started. Remember, you don&#8217;t need to have everything in your website on day one. Start simple and evolve over time.</li>
</ul>
<p>With that in mind, following were 2 personas I had for cloudnineapps.com:</p>
<ol>
<li>Users: The website users.</li>
<li>Admins: The website administrators.</li>
</ol>
<h2><strong>Goals</strong></h2>
<p>And, following were the key goals.</p>
<ul>
<li>Users
<ul>
<li>A simple site with a clean look and easy navigation. I had no intent to have anything flashy or animated interactions.</li>
<li>Self-registration and Membership Management for users so that they can subscribe to the products and services, participate in communities, etc.</li>
<li>Opt-in/Opt-out newsletter sign up support.</li>
<li>An ability to search the site content.</li>
<li>Typical site pages: Like &#8220;Contact Us&#8221; and &#8220;Feedback&#8221;.</li>
</ul>
</li>
<li>Admin
<ul>
<li>Manage Blogs</li>
<li>Manage Products</li>
<li>Manage Courses</li>
</ul>
</li>
</ul>
<p>As you can see, nothing very fancy here. Now, lets get into how did I go about the setup.</p>
<h2>Development Site Setup</h2>
<p>Being a developer, I decided to roll my sleeves and get a development site setup on my laptop. Following are the details of my development environment.</p>
<ul>
<li>PHP 7.1 (<a href="http://php.net/manual/en/install.php">link</a>)</li>
<li>Apache (<a href="http://www.apache.org/dyn/closer.cgi">link</a>) &#8211; I reused my existing Apache installation</li>
<li>MySQL (<a href="https://dev.mysql.com/downloads/installer/">link</a>) &#8211; I reused my existing MySQL installation</li>
<li>phpMyAdmin (<a href="https://www.phpmyadmin.net/">link</a>) &#8211; Not a must, but highly recommended</li>
<li>WordPress (<a href="https://wordpress.org/download/">link</a>)</li>
</ul>
<p><span style="text-decoration: underline;">Tip</span>: Even though we are starting here with the Development Site, our goal should be to set it up with configurations, best practices and security similar to what we would do in production. This way you can also test it out before rolling out such changes in production directly.</p>
<h3>Apache Setup</h3>
<p>I prefer to use <a href="https://httpd.apache.org/docs/2.4/vhosts/">VirtualHost</a> as that helps avoid installing multiple apache installations just to keep their configuration and deployment separate. It lets you do all that and it works like a charm as you can host multiple virtualhosts if you run multiple sites. Here&#8217;s the VirtualHost configuration I used.</p>
<pre class="lang:apache decode:true" title="ApacheVirtualHostConfig"># VirtualHost: cloudnineapps
&lt;VirtualHost *&gt;
  ServerName cloudnineapps
  ServerAlias *.cloudnineapps
  DocumentRoot /sites/cloudnineapps/www
  DirectoryIndex index.php
  &lt;Directory "/sites/cloudnineapps/www"&gt;
    Options Indexes FollowSymLinks
    AllowOverride All
    Order deny,allow
    Allow from all
    Require all granted
  &lt;/Directory&gt;
&lt;/VirtualHost&gt;
</pre>
<p>Few tips and tricks to use this.</p>
<ul>
<li>Create an entry in the <strong>/etc/hosts</strong> file for the site.
<pre class="lang:default decode:true " title="EtcHost">127.0.0.1 cloudnineapps</pre>
<p>Now you can access the website using local browser.<br />
http://cloudnineapps/</p>
</li>
<li>Other entries in VirtualHost specify the root directory for site content and basic permissions.</li>
<li>I created an <strong>.htaccess</strong> under <strong>DocumentRoot</strong>.
<pre class="lang:apache decode:true">&lt;IfModule mod_rewrite.c&gt;
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.php$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.php [L]
&lt;/IfModule&gt;
</pre>
<p>The admin URL will be: http://cloudnineapps/wp-admin</p>
</li>
</ul>
<h3>Database Setup</h3>
<p>Since I already had MySQL installed, I simply created a new database for my Development Site.</p>
<pre class="lang:mysql decode:true" title="DBCreateScript">create database cloudnineapps_wp;
create user 'c9dbuser'@'localhost' identified by 'password';
grant all privileges on cloudnineapps_wp.* to 'c9dbuser'@'localhost' identified by 'password';
flush privileges;
</pre>
<p><span style="text-decoration: underline;">Tip</span>: Please use a strong password for database.</p>
<h3>WordPress Setup</h3>
<h4>WordPress Installation</h4>
<ul>
<li>Extract the content of the wordpress zip and copy the extracted files under the <strong>DocumentRoot</strong> above.</li>
<li>Ensure to give write permissions to the user that apache is running as. Example for Mac
<pre class="lang:sh decode:true " title="DocumentRootPermissions">sudo chown -R _www:staff /sites/cloudnineapps/www</pre>
</li>
<li>You are now ready to launch the WordPress installation by going to the home page.<br />
http://cloudnineapps/<br />
<span style="text-decoration: underline;">Tip</span>: Specify appropriate title, admin user credentials and email. Again, as a practice, use strong password.</li>
<li>It may take a few minutes to complete the installation. Typically, it&#8217;s fairly quick.</li>
</ul>
<h4>WordPress Configuration</h4>
<p>WordPress is heavily customizable without writing a single bit of code. Here are the settings that I tweaked for the Development Site.</p>
<table>
<tbody>
<tr>
<th>Category</th>
<th>Setting</th>
<th>Purpose</th>
<th>Value</th>
</tr>
<tr>
<td>Settings-&gt;General</td>
<td>WordPress Address</td>
<td>The authoring website.</td>
<td>cloudnineapps.com</td>
</tr>
<tr>
<td>Settings-&gt;General</td>
<td>Site Address</td>
<td>The public website. Keep same as the above WordPress Address to avoid CORS.</td>
<td>cloudnineapps.com</td>
</tr>
<tr>
<td>Settings-&gt;Reading</td>
<td>Search Engine Visibility</td>
<td>Turn search indexing on/off.</td>
<td>Unchecked (for Development Site)</td>
</tr>
<tr>
<td>Settings-&gt;Permalinks</td>
<td>&nbsp;</td>
<td>The post URL format.</td>
<td>/%category%/%postname%/</td>
</tr>
</tbody>
</table>
<h4>WordPress Theme Setup</h4>
<p>A WordPress Theme determines the overall layout of your site, the look and feel and many such user interface related aspects. Choosing a WordPress theme is literally like going to a mall where you&#8217;ve tons of choices. This could take a few minutes and sometimes even days. I suggest to choose something reasonable because in many cases you can always come back and choose a better theme of your choice. I did so various times. And, I did not notice any data loss or such.</p>
<p><span style="text-decoration: underline;">Tip</span>: A good time to finalize your theme would be right after you&#8217;ve done the basic setup and testing, but before you prepare a lot of content. This is important as at times, the way theme presents data may lead you to organize or format your content differently.</p>
<p>For my purpose, I found the <a href="https://axlethemes.com/downloads/best-business/">Best Business Theme</a> to be adequate. You can search and install themes from the admin&#8217;s <strong>Appearance-&gt;Theme</strong> option.</p>
<h4>WordPress Plugins Setup</h4>
<p>A WordPress Plugin provides specific capabilities that could range from simple presentation/formatting to more complex things like e-commerce, course management, etc. Alike theme, choosing the right set of plugins can also be daunting. Often there are multiple plugins that serve same or similar purpose. Contrary to theme, I do recommend spending a bit more time identifying the plugins early on. At least, on the most important ones that you want. Several plugins directly impact the way you would author content. Hence, it is worth taking time on the most important plugins. Here&#8217;s the list that I picked. You can search and install plugins from the admin&#8217;s <strong>Plugins</strong> menu.</p>
<table>
<tbody>
<tr>
<th>Plugin</th>
<th>Purpose</th>
</tr>
<tr>
<td>Contact Form 7</td>
<td>A very flexible forms plugin.</td>
</tr>
<tr>
<td>HC Custom WP-Admin URL</td>
<td>Protects WordPress URL by providing a custom slug (instead of the default &#8216;wp-admin&#8217;).</td>
</tr>
<tr>
<td>LearnPress</td>
<td>Provides online course management capabilities.</td>
</tr>
<tr>
<td>MailChimp for WordPress</td>
<td>Provides integration with the popular MailChimp bulk mailer.</td>
</tr>
<tr>
<td>Post Tags and Categories for Pages</td>
<td>Provides categories support for pages.</td>
</tr>
<tr>
<td>TablePress</td>
<td>Provides beautiful tables.</td>
</tr>
<tr>
<td>Ultimate Member</td>
<td>Member registration and self management.</td>
</tr>
</tbody>
</table>
<p>That&#8217;s it! You are now ready to start using your Development Site.</p>
<h2>Author&#8230; Test&#8230; Improve&#8230;</h2>
<p>You put your heart and soul in getting the site setup. Now it&#8217;s time to put content that would interest your target audience. Start simple. Author a few different type of content, such as, a couple blog posts, pages, etc to get a feel. You may also find better theme and plugins along the way. And, that&#8217;s why I call it a journey. It&#8217;s not the end. It&#8217;s the beginning!</p>
<h2>Promote to Production</h2>
<p>Once you&#8217;ve perfected the Development Site to a level where you feel comfortable rolling it out to the public, look for an appropriate hosting provider. At this point, I do not have a strong recommendation. But, look at the popular WordPress tutorial sites. They often provide links to hosting providers with coupons as well. As far as pushing content to production is concerned, I did it using the following steps.</p>
<h2>Production Database Setup</h2>
<ul>
<li>Backup source database (as SQL using phpMyAdmin).</li>
<li>Replace the references from local site to the target site (e.g., &#8220;http://cloudnineapps/&#8221; by &#8220;https://cloudnineapps.com&#8221;).</li>
<li>Login to cPanel of your hosting provider and launch phpMyAdmin.</li>
<li>Drop all tables.</li>
<li>If changing the table prefix, do the following.
<ul>
<li>Update all the <strong>wp_*</strong> tables to use <strong>table_prefix</strong>.</li>
<li>Update the names of the following to use the <strong>table_prefix</strong> in wp-config.php instead of <strong>wp_</strong>.
<ul>
<li><strong>&lt;table_prefix&gt;_usermetdata</strong>
<ul>
<li>wp_capabilities</li>
<li>wp_user_level</li>
<li>wp_dashboard_quick_press_last_post_id</li>
<li>wp_user-settings</li>
<li>wp_user-settings-time</li>
</ul>
</li>
<li><strong>&lt;table_prefix&gt;_options</strong>
<ul>
<li>wp_user_roles</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Import above updated SQL.</li>
<li>Update the following rows in the <strong>&lt;table_prefix&gt;_options</strong> table to use the correct site URL.
<ul>
<li>siteurl</li>
<li>home</li>
</ul>
</li>
</ul>
<h2>Production WordPress Content Promotion</h2>
<p>Once the production has WordPress installed, do the following.</p>
<ul>
<li>Copy the wordpress folder (except <strong>.htaccess</strong> and <strong>wp-config.php</strong>).</li>
<li><strong>wp-config.php</strong> updates
<ul>
<li>Ensure the <strong>DB_NAME</strong>, <strong>DB_USER</strong>, <strong>DB_PASSWORD</strong> and <strong>DB_HOST</strong> point to the correct database info.</li>
<li>If changing table prefix, ensure to update the <strong>table_prefix</strong>.</li>
</ul>
</li>
<li>Enable HTTPS.</li>
</ul>
<p>&nbsp;</p>
<p>And, let your WordPress journey begin.</p>
<p>Good luck!<br />
&#8211; Nitin</p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Build smart reusable content that is easy to maintain.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/"><img class="wp-image-728 size-full aligncenter" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables/c9-variables-small.png?resize=128%2C128&#038;ssl=1" alt="" width="128" height="128" data-recalc-dims="1" /></a></p>
<center><strong><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables/">C9 Variables</a> (FREE)</strong></center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/"><img class="wp-image-663 size-full aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/products/wordpress-plugins/c9-variables-pro/c9-variables-pro-small.png?resize=128%2C128&#038;ssl=1" alt="" width="128" height="128" data-recalc-dims="1" /></a></p>
<center><strong><a href="https://cloudnineapps.com/products/wordpress-plugins/c9-variables-pro/">C9 Variables Pro</a></strong></center>
<p></div></div> </div></div></div></p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fgetting-started-wordpress-developers-webmasters%2F&amp;linkname=Getting%20Started%20With%20WordPress%20for%20Developers" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fgetting-started-wordpress-developers-webmasters%2F&amp;linkname=Getting%20Started%20With%20WordPress%20for%20Developers" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fgetting-started-wordpress-developers-webmasters%2F&amp;linkname=Getting%20Started%20With%20WordPress%20for%20Developers" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fgetting-started-wordpress-developers-webmasters%2F&amp;linkname=Getting%20Started%20With%20WordPress%20for%20Developers" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fgetting-started-wordpress-developers-webmasters%2F&#038;title=Getting%20Started%20With%20WordPress%20for%20Developers" data-a2a-url="https://cloudnineapps.com/blogs/wordpress/getting-started-wordpress-developers-webmasters/" data-a2a-title="Getting Started With WordPress for Developers"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/getting-started-wordpress-developers-webmasters/">Getting Started With WordPress for Developers</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/wordpress/getting-started-wordpress-developers-webmasters/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">495</post-id>	</item>
		<item>
		<title>WordPress &#8211; A Journey Has Begun!</title>
		<link>https://cloudnineapps.com/blogs/wordpress/wordpress-journey-begun/</link>
					<comments>https://cloudnineapps.com/blogs/wordpress/wordpress-journey-begun/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Tue, 05 Dec 2017 03:14:42 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=454</guid>

					<description><![CDATA[<p>A few months back I decided to do a relaunch of CloudNineApps site. All I was looking for was a fresh look and feel a platform on which I can continue to serve content to our users more quickly (things&#8230;&#160;<a href="https://cloudnineapps.com/blogs/wordpress/wordpress-journey-begun/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/wordpress-journey-begun/">WordPress &#8211; A Journey Has Begun!</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>A few months back I decided to do a relaunch of CloudNineApps site. All I was looking for was</p>
<ul>
<li>a fresh look and feel</li>
<li>a platform on which I can continue to serve content to our users more quickly (things like courses, blogs, etc)</li>
<li>easy maintenance</li>
</ul>
<p>Being a developer and having built several content management solutions in the past, choosing the option of technologies and platforms I was familiar with was an obvious choice. However, I decided to take a plunge and pick something new. I had read cursorily about WordPress and doing a bit more research grabbed my attention. And, I decided to learn more. I did my initial set up and porting of existing website fairly quickly. But, as I played more with the tool I started seeing more and more value. For anything, you may want to do chances are high that there is already an existing theme or plugin and the community support is fabulous. But, that&#8217;s not it. As a developer, it opens up a world of possibilities to provide solutions that can add value to the users. And, that&#8217;s precisely where I am. I started as a consumer of this excellent platform. But, I see this as a start of the journey. And, I look forward to building more value-added solutions.</p>
<p>Stay tuned!<br />
&#8211; Nitin</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwordpress-journey-begun%2F&amp;linkname=WordPress%20%E2%80%93%20A%20Journey%20Has%20Begun%21" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwordpress-journey-begun%2F&amp;linkname=WordPress%20%E2%80%93%20A%20Journey%20Has%20Begun%21" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwordpress-journey-begun%2F&amp;linkname=WordPress%20%E2%80%93%20A%20Journey%20Has%20Begun%21" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwordpress-journey-begun%2F&amp;linkname=WordPress%20%E2%80%93%20A%20Journey%20Has%20Begun%21" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fwordpress%2Fwordpress-journey-begun%2F&#038;title=WordPress%20%E2%80%93%20A%20Journey%20Has%20Begun%21" data-a2a-url="https://cloudnineapps.com/blogs/wordpress/wordpress-journey-begun/" data-a2a-title="WordPress – A Journey Has Begun!"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/wordpress/wordpress-journey-begun/">WordPress &#8211; A Journey Has Begun!</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/wordpress/wordpress-journey-begun/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">454</post-id>	</item>
	</channel>
</rss>
