Error: Cannot fetch feed url - Cannot fetch feed url - A Better Planet - WordPress News News and updates from the world of WordPress 2020-03-19T14:08:59+01:00 text/html 2020-03-19T12:30:00+01:00 A Better Planet A Practical Overview Of CSS Houdini <html> <head> <meta charset="utf-8"> <link rel="canonical" href="" /> <title>A Practical Overview Of CSS Houdini</title> </head> <body> <article> <header> <h1>A Practical Overview Of CSS Houdini</h1> <address>Adrian Bece</address> <time datetime="2020-03-19T12:30:00&#43;00:00" class="op-published">2020-03-19T12:30:00+00:00</time> <time datetime="2020-03-19T12:30:00&#43;00:00" class="op-modified">2020-03-19T13:03:29+00:00</time> </header> <p>It takes a long time for a new CSS feature or improvement to progress from an initial draft to a fully-supported and stable CSS feature that developers can use. JavaScript-based polyfills can be used as a substitute for the lack of browser support in order to use new CSS features before they’re officially implemented. But they are flawed in most cases. For example, <a href="">scrollsnap-polyfill</a> is one of several polyfills that can be used to fix browser support inconsistencies for the CSS Scroll Snap specification. But even that solution has some limitations, bugs and inconsistencies.</p> <p>The potential downside to using polyfills is that they can have a <a href="">negative impact on performance</a> and are difficult to implement properly. This downside is related to the browser’s DOM and CSSOM. Browser creates a <strong>DOM (Document Object Model)</strong> from HTML markup and, similarly, it created <strong>CSSOM (CSS Object Model)</strong> from CSS markup. These two object trees are independent of one another. JavaScript works on DOM and has very limited access to CSSOM.</p> <p>JavaScript Polyfill solutions run only after the initial render cycle has been completed, i.e. when both DOM and CSSOM have been created and the document has finished loading. After Polyfill makes changes to styles in the DOM (by inlining them), it causes the render process to run again and the whole page re-renders. Negative performance impact gets even more apparent if they rely on the <code>requestAnimationFrame</code> method or depend on user interactions like scroll events.</p> <p>Another obstacle in web development is various <strong>constraints imposed by the CSS standards</strong>. For example, there are only a limited number of CSS properties that can be natively animated. CSS knows how to natively animate colors, but doesn&rsquo;t know how to animate gradients. There has always been a need to innovate and create impressive web experiences by pushing the boundaries despite the tech limitations. That is why developers often tend to gravitate towards using less-than-ideal workarounds or JavaScript to implement more advanced styling and effects that are currently not supported by CSS such as masonry layout, advanced 3D effects, advanced animation, fluid typography, animated gradients, styled <code>select</code> elements, etc.</p> <p>It seems <strong>impossible for CSS specifications to keep up</strong> with the various <a href="">feature demands from the industry</a> such as more control over animations, improved text truncation, better styling option for <code>input</code> and <code>select</code> elements, more <code>display</code> options, more <code>filter</code> options, etc.</p> <p>What could be the potential solution? Give developers a <strong>native way of extending CSS using various APIs</strong>. In this article, we are going to take a look at how frontend developers can do that using Houdini APIs, JavaScript, and CSS. In each section, we’re going to examine each API individually, check its browser support and current specification status, and see how they can be implemented today using Progressive enhancement.</p> <div data-component="FeaturePanel" data-audience="non-subscriber" data-remove="true" class="feature-panel-container hidden"></div> <h3 id="what-is-houdini">What Is Houdini?</h3> <p>Houdini, an umbrella term for the collection of browser APIs, aims to bring significant improvements to the web development process and the development of CSS standards in general. Developers will be able to extend the CSS with new features using JavaScript, hook into CSS rendering engine and tell the browser how to apply CSS during a render process. This will result in significantly better performance and stability than using regular polyfills.</p> <p>Houdini specification consists of two API groups - <strong>high-level APIs</strong> and <strong>low-level APIs</strong>.</p> <p><strong>High-level APIs</strong> are closely related to the browser’s rendering process (style → layout → paint → composite). This includes:</p> <ul> <li><strong>Paint API</strong><br /> An extension point for the browser’s paint rendering step where visual properties (color, background, border, etc.) are determined.</li> <li><strong>Layout API</strong><br /> An extension point for the browser’s layout rendering step where element dimensions, position, and alignment are determined.</li> <li><strong>Animation API</strong><br /> An extension point for browser’s composite rendering step where layers are drawn to the screen and animated.</li> </ul> <p><strong>Low-Level API</strong>s form a foundation for high-level APIs. This includes:</p> <ul> <li>Typed Object Model API</li> <li>Custom Properties &amp; Values API</li> <li>Font Metrics API</li> <li>Worklets</li> </ul> <p>Some Houdini APIs are already available for use in <a href="">some browsers</a> with other APIs to follow suit when they’re ready for release.</p> <h3 id="the-future-of-css">The Future Of CSS</h3> <p>Unlike regular CSS feature specifications that have been introduced thus far, Houdini stands out by allowing developers to extend the CSS in a more native way. Does this mean that CSS specifications will stop evolving and no new official implementations of CSS features will be released? Well, that is not the case. Houdini’s goal is to aid the CSS feature development process by allowing developers to create working prototypes that can be easily standardized.</p> <p>Additionally, developers will be able to share the open-source CSS Worklets more easily and with less need for browser-specific bugfixes.</p> <div class="sponsors__lead-place"></div> <h3 id="typed-object-model-api">Typed Object Model API</h3> <p>Before Houdini was introduced, the only way for JavaScript to interact with CSS was by parsing CSS represented as string values and modifying them. Parsing and overriding styles manually can be difficult and error-prone due to the value type needing to be changed back and forth and value unit needing to be manually appended when assigning a new value.</p> <pre><code class="language-css"> = newFontSize + "px"; // newFontSize = 20 console.log(; // "20px" </code></pre> <p><strong>Typed Object Model (Typed OM)</strong> API adds more semantic meaning to CSS values by exposing them as typed JavaScript objects. It significantly improves the related code and makes it more performant, stable and maintainable. CSS values are represented by the <code>CSSUnitValue</code> interface which consists of a value and a unit property.</p> <pre><code class="language-css">{ value: 20, unit: "px" } </code></pre> <p>This new interface can be used with the following new properties:</p> <ul> <li><code>computedStyleMap()</code>: for parsing computed (non-inline) styles. This is a method of selected element that needs to be invoked before parsing or using other methods.</li> <li><code>attributeStyleMap</code>: for parsing and modifying inline styles. This is a property that is available on a selected element.</li> </ul> <div class="break-out"> <pre><code class="language-javascript">// Get computed styles from stylesheet (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Set inline styles selectedElement.attributeStyleMap.set("font-size", CSS.em(2)); // Sets inline style selectedElement.attributeStyleMap.set("color", "blue"); // Sets inline style // Computed style remains the same (initial value) selectedElement.computedStyleMap().get("font-size"); // { value: 20, unit: "px"} // Get new inline style selectedElement.attributeStyleMap.get("font-size"); // { value: 2, unit: "em"} </code></pre> </div> <p>Notice how specific CSS types are being used when setting a new numeric value. By using this syntax, many potential type-related issues can be avoided and the resulting code is more reliable and bug-free.</p> <p>The <code>get</code> and <code>set</code> methods are only a small subset of all available methods defined by the Typed OM API. Some of them include:</p> <ul> <li><code>clear</code>: removes all inline styles</li> <li><code>delete</code>: removes a specified CSS property and its value from inline styles</li> <li><code>has</code>: returns a boolean if a specified CSS property is set</li> <li><code>append</code>: adds an additional value to a property that supports multiple values</li> <li>etc.</li> </ul> <h4 id="feature-detection">Feature detection</h4> <div class="break-out"> <pre><code class="language-javascript">var selectedElement = document.getElementById("example"); if(selectedElement.attributeStyleMap) { /&#42; ... &#42;/ } if(selectedElement.computedStyleMap) { /&#42; ... &#42;/ } </code></pre> </div> <h4 id="w3c-specification-status">W3C Specification Status</h4> <ul> <li><a href="">Working Draft</a>: published for review by the community</li> </ul> <h4 id="browser-support">Browser Support</h4> <table class="tablesaw table--no-stripe break-out table-saw" data-tablesaw-mode="stack" data-tablesaw-minimap> <thead> <tr> <th>Google Chrome</th> <th>Microsoft Edge</th> <th>Opera Browser</th> <th>Firefox</th> <th>Safari</th> </tr> </thead> <tbody> <tr> <td>Supported</td> <td>Supported</td> <td>Supported</td> <td>Not supported</td> <td>Partial support (*)</td> </tr> </tbody> </table> <p><sup>*</sup> <em>supported with “Experimental Web Platform features” or other feature flag enabled.</em></p> <p><em>Data source: <a href="">Is Houdini Ready Yet?</a></em></p> <h3 id="custom-properties-and-values-api">Custom Properties And Values API</h3> <p>The <em>CSS Properties And Values</em> API allows developers to extend CSS variables by adding a type, initial value and define inheritance. Developers can define CSS custom properties by registering them using the <code>registerProperty</code> method which tells the browsers how to transition it and handle fallback in case of an error.</p> <pre><code class="language-css">CSS.registerProperty({ name: "--colorPrimary", syntax: "&lt;color&gt;", inherits: false, initialValue: "blue", }); </code></pre> <p>This method accepts an input argument that is an object with the following properties:</p> <ul> <li><code>name</code>: the name of the custom property</li> <li><code>syntax</code>: tells the browser how to parse a custom property. These are pre-defined values like <code>&lt;color&gt;</code>, <code>&lt;integer&gt;</code>, <code>&lt;number&gt;</code>, <code>&lt;length&gt;</code>, <code>&lt;percentage&gt;</code>, etc.</li> <li><code>inherits</code>: tells the browser whether the custom property inherits its parent’s value.</li> <li><code>initialValue</code>: tells the initial value that is used until it’s overridden and this is used as a fallback in case of an error.</li> </ul> <div class="sponsors__lead-place"></div> <p>In the following example, the <code>&lt;color&gt;</code> type custom property is being set. This custom property is going to be used in gradient transition. You might be thinking that current CSS doesn’t support transitions for background gradients and you would be correct. Notice how the custom property itself is being used in <code>transition</code>, instead of a <code>background</code> property that would be used for regular <code>background-color</code> transitions.</p> <div class="break-out"> <pre><code class="language-css">.gradientBox { background: linear-gradient(45deg, rgba(255,255,255,1) 0%, var(--colorPrimary) 60%); transition: --colorPrimary 0.5s ease; /&#42; ... &#42;/ } .gradientBox:hover { --colorPrimary: red /&#42; ... &#42;/ } </code></pre> </div> <p>Browser doesn’t know how to handle gradient transition, but it knows how to handle color transitions because the custom property is specified as <code>&lt;color&gt;</code> type. On a browser that supports Houdini, a gradient transition will happen when the element is being hovered on. Gradient position percentage can also be replaced with CSS custom property (registered as <code>&lt;percentage&gt;</code> type) and added to a transition in the same way as in the example.</p> <p>If <code>registerProperty</code> is removed and a regular CSS custom property is registered in a <code>:root</code> selector, the gradient transition won’t work. It’s required that <code>registerProperty</code> is used so the browser knows that it should treat it as color.</p> <p>In the future implementation of this API, it would be possible to register a custom property directly in CSS.</p> <pre><code class="language-css">@property --colorPrimary { syntax: "&lt;color&gt;"; inherits: false; initial-value: blue; } </code></pre> <h4 id="example">Example</h4> <p>This simple example showcases gradient color and position transition on hover event using registered CSS custom properties for color and position respectively. Complete source code is available on the <a href="">example repository</a>.</p> <figure class="break-out"><a href=""><img src="" alt="" /></a><figcaption>Animated gradient color and position using Custom Properties & Values API. Delay for each property added for effect in CSS transition property. (<a href="">Large preview</a>)</figcaption></figure> <h4 id="feature-detection-1">Feature Detection</h4> <pre><code class="language-css">if (CSS.registerProperty) { /&#42; ... &#42;/ } </code></pre> <h4 id="w3c-specification-status-1">W3C Specification Status</h4> <ul> <li><a href="">Working Draft</a>: published for review by the community</li> </ul> <h4 id="browser-support-1">Browser Support</h4> <table class="tablesaw table--no-stripe break-out table-saw" data-tablesaw-mode="stack" data-tablesaw-minimap> <thead> <tr> <th>Google Chrome</th> <th>Microsoft Edge</th> <th>Opera Browser</th> <th>Firefox</th> <th>Safari</th> </tr> </thead> <tbody> <tr> <td>Supported</td> <td>Supported</td> <td>Supported</td> <td>Not supported</td> <td>Not supported</td> </tr> </tbody> </table> <p><em>Data source: <a href="">Is Houdini Ready Yet?</a></em></p> <h3 id="font-metrics-api">Font Metrics API</h3> <p>The <em>Font Metrics</em> API is still in a very early stage of development, so its specification may change in the future. In its current draft, <strong>Font Metrics API</strong> will provide methods for measuring dimensions of text elements that are being rendered on screen in order to allow developers to affect how text elements are being rendered on screen. These values are either difficult or impossible to measure with current features, so this API will allow developers to create text and font-related CSS features more easily. Multi-line dynamic text truncation is an example of one of those features.</p> <h4 id="w3c-specification-status-2">W3C Specification Status</h4> <ul> <li><a href="">Collection of Ideas</a>: no specification draft submitted at the moment</li> </ul> <h4 id="browser-support-2">Browser Support</h4> <table class="tablesaw table--no-stripe break-out table-saw" data-tablesaw-mode="stack" data-tablesaw-minimap> <thead> <tr> <th>Google Chrome</th> <th>Microsoft Edge</th> <th>Opera Browser</th> <th>Firefox</th> <th>Safari</th> </tr> </thead> <tbody> <tr> <td>Not supported</td> <td>Not supported</td> <td>Not supported</td> <td>Not supported</td> <td>Not supported</td> </tr> </tbody> </table> <p><em>Data source: <a href="">Is Houdini Ready Yet?</a></em></p> <h3 id="worklets">Worklets</h3> <p>Before moving onto the other APIs, it’s important to explain the Worklets concept. <strong>Worklets</strong> are scripts that run during render and are independent of the main JavaScript environment. They are an extension point for rendering engines. They are designed for parallelism (with 2 or more instances) and thread-agnostic, have reduced access to the global scope and are called by the rendering engine when needed. Worklets can be run only on HTTPS (on production environment) or on localhost (for development purposes).</p> <p>Houdini introduces following Worklets to extend the browser render engine:</p> <ul> <li>Paint Worklet - Paint API</li> <li>Animation Worklet - Animation API</li> <li>Layout Worklet - Layout API</li> </ul> <h3 id="paint-api">Paint API</h3> <p>The Paint API allows developers to use JavaScript functions to draw directly into an element’s background, border, or content using <a href="">2D Rendering Context</a>, which is a subset of the HTML5 Canvas API. Paint API uses Paint Worklet to draw an image that dynamically responds to changes in CSS (changes in CSS variables, for example). Anyone familiar with Canvas API will feel right at home with Houdini’s Paint API.</p> <p>There are several steps required in defining a Paint Worklet:</p> <ol> <li>Write and register a Paint Worklet using the <code>registerPaint</code> function</li> <li>Call the Worklet in HTML file or main JavaScript file using <code>CSS.paintWorklet.addModule</code> function</li> <li>Use the <code>paint()</code> function in CSS with a Worklet name and optional input arguments.</li> </ol> <p>Let’s take a look at the <code>registerPaint</code> function which is used to register a Paint Worklet and define its functionality.</p> <div class="break-out"> <pre><code class="language-css">registerPaint("paintWorketExample", class { static get inputProperties() { return ["--myVariable"]; } static get inputArguments() { return ["&lt;color&gt;"]; } static get contextOptions() { return {alpha: true}; } paint(ctx, size, properties, args) { /&#42; ... &#42;/ } }); </code></pre> </div> <p>The <code>registerPaint</code> function consists of several parts:</p> <ul> <li><code>inputProperties</code>:<br /> An array of CSS custom properties that the Worklet will keep track of. This array represents dependencies of a paint worklet.</li> <li><code>inputArguments</code>:<br /> An array of input arguments that can be passed from <code>paint</code> function from inside the CSS.</li> <li><code>contextOptions</code>: allow or disallow opacity for colors. If set to <code>false</code>, all colors will be displayed with full opacity.</li> <li><code>paint</code>: the main function that provides the following arguments: <ul> <li><code>ctx</code>: 2D drawing context, almost identical to Canvas API’s 2D drawing context.</li> <li><code>size</code>: an object containing the width and height of the element. Values are determined by the layout rendering process. Canvas size is the same as the actual size of the element.</li> <li><code>properties</code>: input variables defined in <code>inputProperties</code></li> <li><code>args</code>: an array of input arguments passed in <code>paint</code> function in CSS</li> </ul></li> </ul> <p>After the Worklet has been registered, it needs to be invoked in the HTML file by simply providing a path to the file.</p> <pre><code class="language-css">CSS.paintWorklet.addModule("path/to/worklet/file.js"); </code></pre> <p>Any Worklet can also be added from an external URL (from a Content Delivery Network, for example) which makes them modular and reusable.</p> <pre><code class="language-css">CSS.paintWorklet.addModule("https://url/to/worklet/file.js"); </code></pre> <p>After the Worklet has been called, it can be used inside CSS using the <code>paint</code> function. This function accepts the Worklet’s registered name as a first input argument and each input argument that follows it is a custom argument that can be passed to a Worklet (defined inside Worklet’s <code>inputArguments</code> ). From that point, the browser determines when to call the Worklet and which user actions and CSS custom properties value change to respond to.</p> <pre><code class="language-css">.exampleElement { /&#42; paintWorkletExample - name of the worklet blue - argument passed to a Worklet &#42;/ background-image: paint(paintWorketExample, blue); } </code></pre> <h4 id="example-1">Example</h4> <p>The following example showcases Paint API and general Worklet reusability and modularity. It’s using the ripple Worklet directly from <a href="">Google Chrome Labs repository</a> and runs on a different element with different styles. Complete source code is available on the <a href="">example repository</a>.</p> <figure class="break-out"><a href=""><img src="" alt="" /></a><figcaption>Ripple effect example (uses Ripple Worklet by Google Chrome Labs) (<a href="">Large preview</a>)</figcaption></figure> <h4 id="feature-detection-2">Feature detection</h4> <pre><code class="language-css">if ("paintWorklet" in CSS) { /&#42; ... &#42;/ } @supports(background:paint(paintWorketExample)){ /&#42; ... &#42;/ } </code></pre> <h4 id="w3c-specification-status-3">W3C Specification Status</h4> <ul> <li><a href="">Candidate recommendation</a>: stable working draft ready for implementation</li> </ul> <h4 id="browser-support-3">Browser Support</h4> <table class="tablesaw table--no-stripe break-out table-saw" data-tablesaw-mode="stack" data-tablesaw-minimap> <thead> <tr> <th>Google Chrome</th> <th>Microsoft Edge</th> <th>Opera Browser</th> <th>Firefox</th> <th>Safari</th> </tr> </thead> <tbody> <tr> <td>Supported</td> <td>Supported</td> <td>Supported</td> <td>Not supported</td> <td>Not supported</td> </tr> </tbody> </table> <p><em>Data source: <a href="">Is Houdini Ready Yet?</a></em></p> <h3 id="animation-api">Animation API</h3> <p>The <em>Animation</em> API extends web animations with options to listen to various events (scroll, hover, click, etc.) and improves performance by running animations on their own dedicated thread using an Animation Worklet. It allows for user action to control the flow of animation that runs in a performant, non-blocking way.</p> <p>Like any Worklet, Animation Worklet needs to be registered first.</p> <pre><code class="language-css">registerAnimator("animationWorkletExample", class { constructor(options) { /&#42; ... &#42;/ } animate(currentTime, effect) { /&#42; ... &#42;/ } }); </code></pre> <p>This class consists of two functions:</p> <ul> <li><code>constructor</code>: called when a new instance is created. Used for general setup.</li> <li><code>animate</code>: the main function that contains the animation logic. Provides the following input arguments: <ul> <li><code>currentTime</code>: the current time value from the defined timeline</li> <li><code>effect</code>: an array of effects that this animation uses</li> </ul></li> </ul> <p>After the Animation Worklet has been registered, it needs to be included in the <strong>main JavaScript file</strong>, animation (element, keyframes, options) needs to be defined and animation is instantiated with the selected timeline. Timeline concepts and web animation basics will be explained in the next section.</p> <div class="break-out"> <pre><code class="language-css">/&#42; Include Animation Worklet &#42;/ await CSS.animationWorklet.addModule("path/to/worklet/file.js");; /&#42; Select element that's going to be animated &#42;/ const elementExample = document.getElementById("elementExample"); /&#42; Define animation (effect) &#42;/ const effectExample = new KeyframeEffect( elementExample, /&#42; Selected element that's going to be animated &#42;/ [ /&#42; ... &#42;/ ], /&#42; Animation keyframes &#42;/ { /&#42; ... &#42;/ }, /&#42; Animation options - duration, delay, iterations, etc. &#42;/ ); /&#42; Create new WorkletAnimation instance and run it &#42;/ new WorkletAnimation( "animationWorkletExample" /&#42; Worklet name &#42;/ effectExample, /&#42; Animation (effect) timeline &#42;/ document.timeline, /&#42; Input timeline &#42;/ {}, /&#42; Options passed to constructor &#42;/ ).play(); /&#42; Play animation &#42;/ </code></pre> </div> <h4 id="timeline-mapping">Timeline Mapping</h4> <p>Web animation is based on timelines and <strong>mapping of the current time to a timeline of an effect’s local time</strong>. For example, let’s take a look at a repeating linear animation with 3 keyframes (start, middle, last) that runs 1 second after a page is loaded (delay) and with a 4-second duration.</p> <p>Effect timeline from the example would look like this (with the 4-second duration with no delay):</p> <table class="tablesaw table--no-stripe break-out table-saw" data-tablesaw-mode="stack" data-tablesaw-minimap> <thead> <tr> <th>Effect timeline (4s duration)</th> <th>Keyframe</th> </tr> </thead> <tbody> <tr> <td>0ms</td> <td>First keyframe - animation starts</td> </tr> <tr> <td>2000ms</td> <td>Middle keyframe - animation in progress</td> </tr> <tr> <td>4000ms</td> <td>Last keyframe - animation ends or resets to first keyframe</td> </tr> </tbody> </table> <p>In order to better understand <code>effect.localTime</code>, by setting its value to 3000ms (taking into account 1000ms delay), resulting animation is going to be locked to a middle keyframe in effect timeline (1000ms delay + 2000ms for a middle keyframe). The same effect is going to happen by setting the value to 7000ms and 11000ms because the animation repeats in 4000ms interval (animation duration).</p> <pre><code class="language-css">animate(currentTime, effect) { effect.localTime = 3000; // 1000ms delay + 2000ms middle keyframe } </code></pre> <p>No animation happens when having a constant <code>effect.localTime</code> value because animation is locked in a specific keyframe. In order to properly animate an element, its <code>effect.localTime</code> needs to be dynamic. It’s required for the value to be a function that depends on the <code>currentTime</code> input argument or some other variable.</p> <p>The following code shows a functional representation of 1:1 (linear function) mapping of a timeline to effect local time.</p> <pre><code class="language-css">animate(currentTime, effect) { effect.localTime = currentTime; // y = x linear function } </code></pre> <table class="tablesaw break-out" data-tablesaw-mode="swipe" data-tablesaw-minimap> <thead> <tr> <th>Timeline (<code>document.timeline</code>)</th> <th>Mapped effect local time</th> <th>Keyframe</th> </tr> </thead> <tbody> <tr> <td><code>startTime</code> + 0ms (elapsed time)</td> <td><code>startTime</code> + 0ms</td> <td>First</td> </tr> <tr> <td><code>startTime</code> + 1000ms (elapsed time)</td> <td><code>startTime</code> + 1000ms (delay) + 0ms</td> <td>First</td> </tr> <tr> <td><code>startTime</code> + 3000ms (elapsed time)</td> <td><code>startTime</code> + 1000ms (delay) + 2000ms</td> <td>Middle</td> </tr> <tr> <td><code>startTime</code> + 5000ms (elapsed time)</td> <td><code>startTime</code> + 1000ms (delay) + 4000ms</td> <td>Last / First</td> </tr> <tr> <td><code>startTime</code> + 7000ms (elapsed time)</td> <td><code>startTime</code> + 1000ms (delay) + 6000ms</td> <td>Middle</td> </tr> <tr> <td><code>startTime</code> + 9000ms (elapsed time)</td> <td><code>startTime</code> + 1000ms (delay) + 8000ms</td> <td>Last / First</td> </tr> </tbody> </table> <p>Timeline isn’t restricted to 1:1 mapping to effect’s local time. Animation API allows developers to <strong>manipulate the timeline mapping</strong> in <code>animate</code> function by using standard JavaScript functions to create complex timelines. Animation also doesn’t have to behave the same in each iteration (if animation is repeated).</p> <p>Animation doesn’t have to depend on the document’s timeline which only starts counting milliseconds from the moment it’s loaded. User actions like scroll events can be used as a timeline for animation by using a <code>ScrollTimeline</code> object. For example, an animation can start when a user has scrolled to 200 pixels and can end when a user has scrolled to 800 pixels on a screen.</p> <div class="break-out"> <pre><code class="language-css">const scrollTimelineExample = new ScrollTimeline({ scrollSource: scrollElement, /&#42; DOM element whose scrolling action is being tracked &#42;/ orientation: "vertical", /&#42; Scroll direction &#42;/ startScrollOffset: "200px", /&#42; Beginning of the scroll timeline &#42;/ endScrollOffset: "800px", /&#42; Ending of the scroll timeline &#42;/ timeRange: 1200, /&#42; Time duration to be mapped to scroll values*/ fill: "forwards" /&#42; Animation fill mode &#42;/ }); ... </code></pre> </div> <p>The animation will automatically adapt to user scroll speed and remain smooth and responsive. Since Animation Worklets are running off the main thread and are connected to a browser’s rending engine, animation that depends on user scroll can run smoothly and be very performant.</p> <h4 id="example-2">Example</h4> <p>The following example showcases how a non-linear timeline implementation. It uses modified <a href="">Gaussian function</a> and applies translation and rotation animation with the same timeline. Complete source code is available on the <a href="">example repository</a>.</p> <figure class="break-out"><a href=""><img src="" alt="" /></a><figcaption>Animation created with Animation API which is using modified Gaussian function time mapping (<a href="">Large preview</a>)</figcaption></figure> <h4 id="feature-detection-3">Feature Detection</h4> <pre><code class="language-css">if (CSS.animationWorklet) { /&#42; ... &#42;/ } </code></pre> <h4 id="w3c-specification-status-4">W3C Specification Status</h4> <ul> <li><a href="">First Public Working Draft</a>: ready for community review, prone to specification change</li> </ul> <h4 id="browser-support-4">Browser Support</h4> <table class="tablesaw table--no-stripe break-out table-saw" data-tablesaw-mode="stack" data-tablesaw-minimap> <thead> <tr> <th>Google Chrome</th> <th>Microsoft Edge</th> <th>Opera Browser</th> <th>Firefox</th> <th>Safari</th> </tr> </thead> <tbody> <tr> <td>Partial support (*)</td> <td>Partial support (*)</td> <td>Partial support (*)</td> <td>Not supported</td> <td>Not supported</td> </tr> </tbody> </table> <p><sup>*</sup> <em>supported with “Experimental Web Platform features” flag enabled.</em></p> <p><em>Data source: <a href="">Is Houdini Ready Yet?</a></em></p> <h3 id="layout-api">Layout API</h3> <p>The <em>Layout</em> API allows developers to extend the browser’s layout rendering process by defining new layout modes that can be used in <code>display</code> CSS property. Layout API introduces new concepts, is very complex and offers a lot of options for developing custom layout algorithms.</p> <p>Similarly to other Worklets, the layout Worklet needs to be registered and defined first.</p> <div class="break-out"> <pre><code class="language-css">registerLayout('exampleLayout', class { static get inputProperties() { return ['--exampleVariable']; } static get childrenInputProperties() { return ['--exampleChildVariable']; } static get layoutOptions() { return { childDisplay: 'normal', sizing: 'block-like' }; } intrinsicSizes(children, edges, styleMap) { /* ... */ } layout(children, edges, constraints, styleMap, breakToken) { /* ... */ } }); </code></pre> </div> <p>Worklet register contains the following methods:</p> <ul> <li><code>inputProperties</code>:<br /> An array of CSS custom properties that the Worklet will keep track of that belongs to a Parent Layout element, i.e. the element that calls this layout. This array represents dependencies of a Layout Worklet.</li> <li><code>childrenInputProperties</code>:<br /> An array of CSS custom properties that the Worklet will keep track of that belong to child elements of a Parent Layout element, i.e. the children of the elements that set this layout.</li> <li><code>layoutOptions</code>: defines the following layout properties: <ul> <li><code>childDisplay</code>: can have a pre-defined value of <code>block</code> or <code>normal</code>. Determines if the boxes will be displayed as blocks or inline.</li> <li><code>sizing</code>: can have a pre-defined value of <code>block-like</code> or <code>manual</code>. It tells the browser to either pre-calculate the size or not to pre-calculate (unless a size is explicitly set), respectively.</li> </ul></li> <li><code>intrinsicSizes</code>: defines how a box or its content fits into a layout context. <ul> <li><code>children</code>: child elements of a Parent Layout element, i.e. the children of the element that call this layout.</li> <li><code>edges</code>: Layout Edges of a box</li> <li><code>styleMap</code>: typed OM styles of a box</li> </ul></li> <li><code>layout</code>: the main function that performs a layout. <ul> <li><code>children</code>: child elements of a Parent Layout element, i.e. the children of the element that call this layout.</li> <li><code>edges</code>: Layout Edges of a box</li> <li><code>constraints</code>: constraints of a Parent Layout</li> <li><code>styleMap</code>: typed OM styles of a box</li> <li><code>breakToken</code>: break token used to resume a layout in case of pagination or printing.</li> </ul></li> </ul> <p>Like in the case of a Paint API, the browser rendering engine determines when the paint Worklet is being called. It only needs to be added to an HTML or main JavaScript file.</p> <pre><code class="language-css">CSS.layoutWorklet.addModule('path/to/worklet/file.js'); </code></pre> <p>And, finally, it needs to be referenced in a CSS file</p> <pre><code class="language-css">.exampleElement { display: layout(exampleLayout); } </code></pre> <h4 id="how-layout-api-performs-layout">How Layout API Performs Layout</h4> <p>In the previous example, <code>exampleLayout</code> has been defined using the Layout API.</p> <pre><code class="language-css">.exampleElement { display: layout(exampleLayout); } </code></pre> <p>This element is called a <strong>Parent Layout</strong> that is enclosed with <strong>Layout Edges</strong> which consists of paddings, borders and scroll bars. Parent Layout consists of child elements which are called <strong>Current Layouts</strong>. Current Layouts are the actual target elements whose layout can be customized using the Layout API. For example, when using <code>display: flex;</code> on an element, its children are being repositioned to form the flex layout. This is similar to what is being done with the Layout API.</p> <p>Each <strong>Current Layout</strong> consists of <strong>Child Layout</strong> which is a layout algorithm for the LayoutChild (element, <code>::before</code> and <code>::after</code> pseudo-elements) and <strong>LayoutChild</strong> is a CSS generated box that only contains style data (no layout data). LayoutChild elements are automatically created by browser rendering engine on style step. Layout Child can generate a <strong>Fragment</strong> which actually performs layout render actions.</p> <h4 id="example-3">Example</h4> <p>Similarly to the Paint API example, this example is importing a masonry layout Worklet directly from <a href="">Google Chrome Labs repository</a>, but in this example, it’s used with image content instead of text. Complete source code is available on the <a href="">example repository</a>.</p> <figure class="break-out"><a href=""><img src="" alt="" /></a><figcaption>Masonry layout example (uses Masonry Worklet by Google Chrome Labs (<a href="">Large preview</a>)</figcaption></figure> <h4 id="feature-detection-4">Feature Detection</h4> <pre><code class="language-css">if (CSS.layoutWorklet) { /&#42; ... &#42;/ } </code></pre> <h4 id="w3c-specification-status-5">W3C Specification Status</h4> <ul> <li><a href="">First Public Working Draft</a>: ready for community review, prone to specification change</li> </ul> <h4 id="browser-support-5">Browser Support</h4> <table class="tablesaw table--no-stripe break-out table-saw" data-tablesaw-mode="stack" data-tablesaw-minimap> <thead> <tr> <th>Google Chrome</th> <th>Microsoft Edge</th> <th>Opera Browser</th> <th>Firefox</th> <th>Safari</th> </tr> </thead> <tbody> <tr> <td>Partial support (*)</td> <td>Partial support (*)</td> <td>Partial support (*)</td> <td>Not supported</td> <td>Not supported</td> </tr> </tbody> </table> <p><sup>*</sup> <em>supported with “Experimental Web Platform features” flag enabled.</em></p> <p><em>Data source: <a href="">Is Houdini Ready Yet?</a></em></p> <h3 id="houdini-and-progressive-enhancement">Houdini And Progressive Enhancement</h3> <p>Even though CSS Houdini doesn’t have optimal browser support yet, it can be used today with progressive enhancement in mind. If you are unfamiliar with Progressive enhancement, it would be worth to check out <a href="">this handy article</a> which explains it really well. If you decide on implementing Houdini in your project today, there are few things to keep in mind:</p> <ul> <li><strong>Use feature detection to prevent errors.</strong><br /> Each Houdini API and Worklet offers a simple way of checking if it’s available in the browser. Use feature detection to apply Houdini enhancements only to browsers that support it and avoid errors.</li> <li><strong>Use it for presentation and visual enhancement only.</strong><br /> Users that are browsing a website on a browser that doesn’t yet support Houdini should have access to the content and core functionality of the website. User experience and the content presentation shouldn’t depend on Houdini features and should have a reliable fallback.</li> <li><strong>Make use of a standard CSS fallback.</strong><br /> For example, regular CSS Custom Properties can be used as a fallback for styles defined using Custom Properties &amp; Values API.</li> </ul> <p>Focus on developing a performant and reliable website user experience first and then use Houdini features for decorative purposes as a progressive enhancement.</p> <h3 id="conclusion">Conclusion</h3> <p>Houdini APIs will finally enable developers to keep the JavaScript code used for style manipulation and decoration closer to the browser’s rendering pipeline, resulting in better performance and stability. By allowing developers to hook into the browser rendering process, they will be able to develop various CSS polyfills that can be easily shared, implemented and, potentially, added to CSS specification itself. Houdini will also make developers and designers less constrained by the CSS limitations when working on styling, layouts, and animations, resulting in new delightful web experiences.</p> <p>CSS Houdini features can be added to projects today, but strictly with progressive enhancement in mind. This will enable browsers that do not support Houdini features to render the website without errors and offer optimal user experience.</p> <p>It’s going to be exciting to watch what the developer community will come up with as Houdini gains traction and better browser support. Here are some awesome examples of Houdini API experiments from the community:</p> <ul> <li><a href="">CSS Houdini Experiments</a></li> <li><a href="">Interactive Introduction to CSS Houdini</a></li> <li><a href="">Houdini Samples by Google Chrome Labs</a></li> </ul> <h4 id="references">References</h4> <ul> <li><a href="">W3C Houdini Specification Drafts</a></li> <li><a href="">State of Houdini (Chrome Dev Summit 2018)</a></li> <li><a href="">Houdini’s Animation Worklet - Google Developers</a></li> <li><a href="">Interactive Introduction to CSS Houdini</a></li> </ul> <div class="signature"> <img src="" alt="Smashing Editorial"> <span>(ra, il)</span> </div> </article> </body> </html> text/html 2020-03-19T11:00:00+01:00 A Better Planet 100+ WooCommerce Plugins with Ronald Gijsel at YITH text/html 2020-03-19T03:26:48+01:00 A Better Planet Physical Distancing <blockquote class="wp-block-quote"><p>I&#8217;ve really had enough of this term &#8220;social distancing.&#8221; That is not at all what we are looking for, is it? It should be &#8220;physical distancing.&#8221; In these times of rampant loneliness (especially for seniors), disconnection, and lack of empathy and compassion, we need the opposite — social connecting. And we need it under these circumstances more than ever. Let&#8217;s be creative in finding new ways to come together.</p><cite><a href="">Adam Gazzaley</a>, M. D., Ph. D, University of California, San Francisco</cite></blockquote> <p></p> text/html 2020-03-19T01:42:44+01:00 A Better Planet Taking care of your mental health in uncertain times, with Dr. Sherry Walling <p>Dr. Sherry Walling is a psychologist and entrepreneur, adept at, &#8220;helping smart people do hard things.&#8221; She was gracious to talk in a Post Status Webinar with Cory Miller, about how to navigate life in uncertain times like we have now.</p> <p>Here's the audio episode:</p> <iframe height="200px" width="100%" frameborder="no" scrolling="no" seamless="" src=""></iframe> <figure class="wp-block-embed-vimeo wp-block-embed is-type-video is-provider-vimeo wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper"> <div class="embed-vimeo" style="text-align: center;"><iframe src="" width="1024" height="576" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div> </div></figure> <hr class="wp-block-separator"/> <h3><strong>Topics discussed </strong></h3> <ul><li>Managing fear, worry, and anxiety</li><li>The Coronavirus, and how to handle it</li><li>Isolation, social distancing, remote work, and our mental health</li><li>Q&A on work boundaries, stress, and more</li></ul> <h3>Links</h3> <ul><li><a href="">Zen Founder</a></li><li><a href="">Dr. Sherry Walling's website</a></li><li><a href="">@zenfounder</a> &#8212; Dr. Walling's Twitter</li><li><a href="">Calm Stability in the Crisis of Coronavirus</a> (ZenFounder podcast)</li></ul> <h3>Episode Parter: <a href="">WordFence</a></h3> <p>If your website is mission-critical you can't afford the downtime, reputation challenges or SEO impact of getting hacked. That's why so many sites rely on the real-time protection provided by&nbsp;<a href="">Wordfence&nbsp;Premium</a>.</p> <p><a href="">Wordfence</a>&nbsp;protects your websites with the best WordPress security available, and offers a powerful and efficient way to manage security for multiple sites in one place with&nbsp;Wordfence&nbsp;Central.</p> text/html 2020-03-18T20:35:32+01:00 A Better Planet Build Custom Templates with the MB Views Add-On for Meta Box <p class="has-drop-cap">Meta Box released its <a href="">MB Views add-on plugin</a> last week. The new extension allows developers to build custom templates from the comfort of their WordPress admin. The goal is to provide an easy-to-use interface for outputting custom fields without editing theme files, but its flexibility pushes the boundaries of full-site editing.</p> <p><strong>Quick take:</strong> MB Views offers a solid developer experience but falls a little short of being friendly for those unfamiliar with code.</p> <p>I have long been a fan of what the <a href="">Meta Box</a> team has done with its core plugin and extensions. The project&rsquo;s developers have created a well-documented code base, written solid documentation, and have generally paid attention to details where others have failed. MB Views is no different. In minutes after activating the extension, I had custom views set up and rolled out on the front end of my test site.</p> <p>The interface is simple enough to pick up almost immediately with enough flexibility to build nearly anything from the WordPress admin.</p> <p>On the whole, the team&rsquo;s new add-on is well worth the price of one of the available <a href="">premium bundles</a>, which range between $79 and $349. It is not without a few minor issues, but that is to be expected with a version 1.0 release.</p> <h2>A Powerful Tool for Front End Editing</h2> <figure class="wp-block-image alignwide size-full"><img data-attachment-id="97941" data-permalink="" data-orig-file="" data-orig-size="896,403" data-comments-opened="0" data-image-meta='{"aperture":"0","credit":"","camera":"","caption":"","created_timestamp":"0","copyright":"","focal_length":"0","iso":"0","shutter_speed":"0","title":"","orientation":"0"}' data-image-title="mb-views-editor" data-image-description="" data-medium-file="" data-large-file="" src="" alt="Screenshot of the MB Views plugin's view code editor." class="wp-image-97941" srcset=" 896w, 300w, 500w, 768w" sizes="(max-width: 896px) 100vw, 896px"><figcaption>Creating a custom view with the plugin&rsquo;s view editor.</figcaption></figure> <p class="has-drop-cap">My experience working with the view-editing screen felt natural. The code editor uses <a href="">Code Mirror</a> and its Oceanic Next theme. It has auto-tabbing and auto-complete built in, so it feels like most offline editors. Developers should feel at home quickly building a custom view.</p> <p>Because I mostly use Tailwind CSS these days, I was able to build a <em>faux</em> email signup form in a couple of minutes and display it directly beneath my posts using the available view settings.</p> <figure class="wp-block-image alignwide size-full"><img data-attachment-id="97942" data-permalink="" data-orig-file="" data-orig-size="896,241" data-comments-opened="0" data-image-meta='{"aperture":"0","credit":"","camera":"","caption":"","created_timestamp":"0","copyright":"","focal_length":"0","iso":"0","shutter_speed":"0","title":"","orientation":"0"}' data-image-title="mb-views-custom-view" data-image-description="" data-medium-file="" data-large-file="" src="" alt="Screenshot of a custom-built email signup form using the MB Views plugin." class="wp-image-97942" srcset=" 896w, 300w, 500w, 768w" sizes="(max-width: 896px) 100vw, 896px"><figcaption>Custom-built email signup form with MB Views.</figcaption></figure> <p>The code editor has a &ldquo;New Field&rdquo; button that opens a slide-out box on the right side of the screen. It allows users to insert post, site, user, and query fields. The options also include custom fields created via the Meta Box plugin.</p> <p>Besides editing the template, users can also add custom CSS and JavaScript directly from the view code editor.</p> <p>The output of these fields are all handled through <a href="">Twig</a>, a modern PHP templating engine. Many PHP developers will already be familiar with Twig and will feel comfortable with its syntax. Through this system, plugin users are not limited to HTML. They can use conditionals and loops to customize the output of their view content.</p> <p>For a better developer experience, it would be nice to see an auto-complete option for inserting new fields instead of clicking the &ldquo;New Field&rdquo; button and then clicking on a particular field. Most likely, developers will begin memorizing the fields over time and simply type them out. Auto-complete would be a nice touch for custom fields.</p> <figure class="wp-block-image alignwide size-full"><img data-attachment-id="97943" data-permalink="" data-orig-file="" data-orig-size="897,338" data-comments-opened="0" data-image-meta='{"aperture":"0","credit":"","camera":"","caption":"","created_timestamp":"0","copyright":"","focal_length":"0","iso":"0","shutter_speed":"0","title":"","orientation":"0"}' data-image-title="mb-views-settings" data-image-description="" data-medium-file="" data-large-file="" src="" alt="Screenshot of the settings meta box for the MB Views plugin." class="wp-image-97943" srcset=" 897w, 300w, 500w, 768w" sizes="(max-width: 897px) 100vw, 897px"><figcaption>View settings and conditionals.</figcaption></figure> <p>Where MB Views really shines is its view settings. The plugin allows views to take over the entire page between the theme header and footer or just the content area. It allows users to choose between displaying a view on singular posts, archive pages, or something custom using its built-in shortcode. Users can further break down where a view appears based on conditions that can be grouped in various ways. It can be as simple or complex as needed. It is not completely on par with what&rsquo;s possible with custom PHP conditionals, but it is close enough to cover the majority of use cases.</p> <p>If someone wanted to try their hand at it, they could use MB Views as an entire site editor. The only real requirement would be to build their theme with a header and footer. At some point, maybe the plugin will allow users to take over the entire page layout, effectively making a theme unnecessary.</p> <h2>Issues and Future Enhancements</h2> <p class="has-drop-cap">Version 1.0 is about shipping something into the hands of users. It is a time when developers get some of their most useful feedback, so I expect the following to be addressed as the developers continue to build upon the plugin in the future. I did not hit any major roadblocks, but I did come across some minor issues and had some ideas for improvement.</p> <p>The first issue I hit made me initially believe the plugin did not work at all. I had chosen to display my custom view on singular posts. This is easy to do via the view settings. You select the &ldquo;Singular&rdquo; type. Then, select &ldquo;Post&rdquo; in the first drop-down select. I had assumed this would make the template appear on all posts. However, nothing happened after saving. None of my custom content appeared on the front end. The problem was there was a second drop-down select, which had not been populated with a value by default. There was an &ldquo;All Posts&rdquo; option I needed to select. It was a quick issue to address, but this is why good defaults are so important in plugin development.</p> <p>There is no revision support. For a code editor in the WordPress admin, it makes sense that users could revert their code to an earlier version. If users only ever create views with minor bits of code, this will be a non-issue. However, the plugin goes as far as allowing users to create an entire page layout between the theme&rsquo;s header and footer. That will sometimes mean a lot of code and the need to backpedal changes.</p> <p>MB Views offers an <code>[mbv]</code> shortcode for outputting a view within shortcode-ready areas, such as post content. However, there is no block equivalent for use in the block editor. At this point, having a shortcode but no block seems like a major oversight. Shortcodes need to die a slow and painful death.</p> <p>The view management screen could use a little love too. It would be nice to see at least a column for the view type. As the list of custom views grows, it may get hard to figure out where each view is used at a glance.</p> <h2>User Friendliness and the Future</h2> <blockquote class="wp-block-quote"><p>You want to get values of Meta Box fields and put them on your front-end templates, but you&rsquo;re not too familiar with coding and don&rsquo;t want to touch theme files?</p></blockquote> <p>MB Views&rsquo; opening description claims the plugin is geared toward users who are not familiar with coding. I am unsure if the average user could take advantage of it without picking up some coding knowledge along the way. The interface is primarily geared toward developers. Quite literally, the view editor is a code editor. It does have an easy-to-click field inserter, but those fields will often be useless without some familiarity with HTML and CSS.</p> <p>The tool is good at what it does, but it almost feels like a stop-gap measure in the era of the block editor.</p> <p>For MB Views to be a more useful end-user tool, it will need to transition to more of a visual, point-and-click interface with design options. Otherwise, it will mostly stay in the land of developers who can customize view output to perfection.</p> <p>I don&rsquo;t necessarily think MB Views must go in that direction if the team wants to focus on a great developer experience. However, it does not currently live up to its claim of friendliness for those less familiar with code.</p> <p>We are still likely at least a year out from a full-site editing experience via the block system. Efforts by the Meta Box team may be best spent integrating view editing within that system. The MB Views add-on is a useful and necessary tool for many Meta Box plugin users today, but it may not have time to gain traction before full-site editing lands in core. At that point, the plugin team will need to already be transitioning into a much different world of user experience with WordPress.</p> text/html 2020-03-18T18:28:33+01:00 A Better Planet Release Model Working Group Chat Postponed <p>Sorry for the very late notice, but tonight <a href="" class="mention"><span class="mentions-prefix">@</span>amykamala</a> and I are not able to host the chat. </p> <p>However, if you are interested in working on it async, here are some <a href="">issues that need help</a>. </p> <p>See you on April 1t (no joke!)</p> <p class="o2-appended-tags"><a href="" class="tag"><span class="tag-prefix">#</span>release-process</a></p> text/html 2020-03-18T17:41:56+01:00 A Better Planet How to Grow Your Membership Site (5 Tips) <p>So, you’ve created a membership site? That’s great! <a href="">Creating a membership site</a> is an effective way to generate recurring revenue from your website because members can pay a monthly or yearly fee in exchange for premium content, products, or services.  </p> <p>Growing a membership site can be difficult, though. So, if your new membership site doesn’t have as many members as you imagined and you’re not making as much money as you had hoped, then something needs to change. </p> <p>Luckily, with just a few tips, you can easily attract new members to your site as well as turn your existing members into your biggest fans. </p> <p>Here’s how to grow your membership site.&nbsp;</p> <h2>1. Promote Your Membership Site</h2> <p>First, if people don’t know that your membership site exists, then you’re not going to get many new members. So, you need to promote your membership site—and promote it a lot! </p> <p>Don’t worry though, you don’t need a big marketing budget in order to promote your membership site to a ton of users online. There are a number of easy and affordable ways to promote your membership site online. </p> <p>One of the most popular and effective ways to promote your membership site is by posting about it on social media. Plus, it’s free! </p> <p>And almost everyone is on social media. In fact, according to <a href="">Hootsuite</a>, 84% of people with access to the internet use social media. Because your potential site members are on social media, you need to be there too. </p> <p>Start creating posts on social media platforms like Facebook, Twitter, and Instagram to promote your membership site. Here’s how Succulents and Sunshine promote its paid course on social media:</p> <figure class="wp-block-image"><img src="" alt=""/></figure> <p><a href="">Image Source</a></p> <p>Remember to use relevant hashtags to widen your reach and make it easier for your target audience to find you online. For example, Succulents and Sunshine often uses hashtags like #Succulents, #SucculentGarden, and #SucculentPlant so that succulent lovers can discover their posts. </p> <p>You can also promote your membership site by: </p> <ul><li>Creating valuable blog posts</li><li><a href="">Adding a popup to your site</a></li><li>Emailing your subscribers</li><li><a href="">Running an online giveaway</a></li><li>Answering questions in online forums like Reddit and Quora</li></ul> <p>The more you promote your membership site online, the more members you can attract.&nbsp;</p> <h2>2. Display Social Proof</h2> <p>If you’re struggling to convert website visitors into paying members, you need to add social proof to your website. Social proof is a social and psychological phenomenon where people look to the actions of others in order to determine what their own actions should be in a particular situation. </p> <p>So, if a website visitor is unsure about subscribing to your membership site, but then they see that other people are joining, it encourages them to become a member too. </p> <p>There are a number of ways you can show social proof on your website, like: </p> <ul><li><a href="">Adding reviews and testimonials</a> from members</li><li>Displaying the number of members your site has</li><li>Using trust seals such as accepted payment badges</li><li>Sharing your industry certifications or accreditations&nbsp;</li><li>Showing the number of shares with social sharing buttons</li></ul> <p>You can also show real-time stats to your website visitors with a tool like <a href="">TrustPulse</a>. When a visitor is on your site, with TrustPulse, you can display social proof notifications on the screen every time someone signs up for your membership site. </p> <figure class="wp-block-image"><img src="" alt=""/></figure> <p>By showing social proof on your website, you can skyrocket your conversions.&nbsp;</p> <h2>3. Reward Your Loyal Members</h2> <p>Aside from attracting new people to your membership site, you also have to keep your existing members <a href="">interested and engaged</a>. One way to do that is by rewarding them. </p> <p>By rewarding your existing members, you can increase loyalty and keep them around for a long time. Plus, rewarding your loyal members can make it easier to upsell them. For instance, if you reward members that are subscribed to your lowest membership tier, those happy members will be more likely to upgrade to a higher tier later on, giving you a boost in revenue. </p> <p>So, how do you reward your loyal members?  </p> <p>You can offer coupons, run members-only giveaways, send your members personalized messages on their birthdays, or gift them some branded merch like t-shirts. </p> <p>You can also reward your members with achievement or activity badges when they interact with your site. With a plugin like <a href="">BadgeOS</a>, you can easily add achievement badges to your website. </p> <figure class="wp-block-image"><img src="" alt=""/></figure> <p><a href="">Image Source</a></p> <p>When your members feel valued and appreciated, they’ll continue to be loyal to your membership site and even become brand ambassadors for you.&nbsp;</p> <h2>4. Create an Affiliate Program</h2> <p>Speaking of turning your members into brand ambassadors, you can also reward your existing members and attract new people to your site by creating an affiliate program. </p> <p>With an affiliate program, your members can promote your membership site, products, or services. Whenever you make a sale through one of your member’s referral links, the member/affiliate gets a small commission. This is a great way to turn your members into brand ambassadors and generate more sales. </p> <p>If you’re worried that creating an affiliate program sounds complicated, don’t worry. There are many easy-to-use affiliate <a href="">WordPress plugins</a> on the market. </p> <p>Some membership plugins even offer built-in affiliate programs. For example, if you use <a href="">MemberPress</a> to create a membership site, they have a built-in affiliate program with their Pro edition called Affiliate Royale. This makes it incredibly easy to set up an affiliate program, set the commission, track your affiliate links, and more.&nbsp;</p> <h2>5. Gather Feedback from Your Members</h2> <p>You can also grow your membership site by gathering feedback from your existing members. Your members know exactly what they want from your site, so you should be getting their feedback and putting it to good use. </p> <p>For instance, when collecting feedback from your members, you could discover that your members want a members-only forum on your site where they can chat with other members. By gathering their feedback, listening to it, and putting it into action, it will make your members feel appreciated and you can make improvements to your membership site that will make them happy. Happier members will lead to increased brand loyalty. </p> <p>You can easily collect feedback from your members by <a href="">adding a customer feedback form to your website</a>. </p> <p>Be sure to include questions on your <a href="">customer survey form</a> like: </p> <ul><li>What features could you not live without?</li><li>What features could you live without?</li><li>What features would you like to see?</li></ul> <p>Getting feedback from your members will help you build a membership site that they love and rave about to all of their friends and family. </p> <p>Growing your membership site takes time, but it doesn’t have to be difficult. With these tips for how to grow your membership site, you can create a successful membership site that generates recurring revenue. With steady, recurring revenue, you can turn your hobby into a fully-fledged business. </p> <p>The post <a rel="nofollow" href="">How to Grow Your Membership Site (5 Tips)</a> appeared first on <a rel="nofollow" href="">Torque</a>.</p> text/html 2020-03-18T15:47:55+01:00 A Better Planet Block Dependent Themes <a href=";mc_eid=975bdebbcd"><h2>Block Dependent Themes&nbsp;&rarr;</h2></a><p>An interesting thing as Gutenberg grows is that it&#8217;s aiming to impact both WordPress themes and page builders. And to do this, we may need or want a way for a theme to say it required a specific Gutenberg block to function. I have not thought deeply about it, but I see that Mel Choyce is. So please consider and opine with her about this possibility. Here are two parts of her initial proposal:</p> <blockquote> <h3>Themes can specify blocks.</h3> <p>When creating a theme, you can specify specific blocks from the Block Directory to include with your theme. These could be blocks you’ve written, or other blocks you’ve accounted for in your theme styles.</p> <h3>Activate blocks on theme activation.</h3> <p>When someone activates (not installs) your theme, WordPress can silently download the blocks from the Block Directory.</p></blockquote> <div class="feedflare"> <a href=""><img src="" border="0"></img></a> <a href=""><img src="" border="0"></img></a> <a href=""><img src="" border="0"></img></a> <a href=""><img src="" border="0"></img></a> <a href=""><img src="" border="0"></img></a> </div><img src="" height="1" width="1" alt=""/> text/html 2020-03-18T14:45:54+01:00 A Better Planet issue#451 text/html 2020-03-18T11:00:00+01:00 A Better Planet How to Create Valuable Content for Your Blog text/html 2020-03-17T21:24:24+01:00 A Better Planet WordPress 5.4 RC3 <p>The third release candidate for WordPress 5.4 is now available!</p> <p>WordPress 5.4 is currently scheduled to be released on&nbsp;<strong><a href="">March 31 2020</a></strong>, and we need&nbsp;<em>your</em>&nbsp;help to get there—if you haven’t tried 5.4 yet, now is the time!</p> <p>There are two ways to test the WordPress 5.4 release candidate:</p> <ul><li>Try the&nbsp;<a href="">WordPress Beta Tester</a>&nbsp;plugin (choose the “bleeding edge nightlies” option)</li><li>Or&nbsp;<a href="">download the release candidate here</a>&nbsp;(zip).</li></ul> <p>For details about what to expect in WordPress 5.4, please see the&nbsp;<a href="">first release candidate post</a>.</p> <p>RC3 addresses improvements to the new About page and&nbsp;<a href=";milestone=5.4&amp;group=component&amp;col=id&amp;col=summary&amp;col=milestone&amp;col=owner&amp;col=type&amp;col=status&amp;col=priority&amp;order=priority">8 fixes</a>&nbsp;for the following bugs and regressions:</p> <ul><li><a href=""></a><a href="">49657</a> &#8211; <a href="">Block Editor: Update WordPress Packages WordPress 5.4 RC 3</a></li><li><a href=""></a><a href="">49621</a> &#8211; <a href="">Travis: Download Chromium for E2E Tests Only</a></li><li><a href=""></a><a href="">48164</a> &#8211; <a href="">media_sideload_image Should Store Original URL and Optionally Check for Dupes</a></li><li><a href="">49577 &#8211; Site Health Status Dashboard Provides Incorrect Items Count on Initial Load</a></li><li><a href="">47053 &#8211; Accessibility: Need to set proper &#8216;tabindex&#8217; in &#8216;Skip To Toolbar&#8217; HTML</a></li><li><a href="">48303 &#8211; Docblock Improvements for 5.4</a></li><li><a href="">49374 &#8211; Use get_post_states to Denote Special Pages on the Added Menu Item Accordions</a></li><li><a href="">49619 &#8211; Use &lt;hr /&gt; Instead of Margin on Freedoms Page</a></li></ul> <h2>Plugin and Theme Developers</h2> <p>Please test your plugins and themes against WordPress 5.4 and update the&nbsp;<em>Tested up to</em>&nbsp;version in the readme to 5.4. If you find compatibility problems, please be sure to post to the&nbsp;<a href="">support forums</a>&nbsp;so we can figure those out before the final release.</p> <p>The&nbsp;<a href="">WordPress 5.4 Field Guide</a>&nbsp;has also been published, which details the major changes.</p> <h2>How to Help</h2> <p>Do you speak a language other than English?&nbsp;<a href="">Help us translate WordPress into more than 100 languages!</a></p> <p><em><strong>If you think you’ve found a bug</strong>, you can post to the&nbsp;<a href="">Alpha/Beta area</a>&nbsp;in the support forums. We’d love to hear from you! If you’re comfortable writing a reproducible bug report,&nbsp;<a href="">file one on WordPress Trac</a>, where you can also find&nbsp;<a href="">a list of known bugs</a>.</em></p> text/html 2020-03-17T19:01:46+01:00 A Better Planet Liquid Web Discount – 35% Discount On 3-Months Managed WordPress / WooCommerce Hosting Plans! text/html 2020-03-17T16:02:33+01:00 A Better Planet Opinions & podcasts in a WordPress business text/html 2020-03-17T10:08:50+01:00 A Better Planet Classifieds Theme Review: A Perfect Theme For Your Classifieds Ads Website text/html 2020-03-10T18:06:10+01:00 A Better Planet Creating a Simple Membership Site with Restrict Content Pro <h2>What's the right plugin for a simple membership site?</h2> <p>The other day I got an email that likely sounds familiar, if you've ever tried to create a simple membership site and realized there were a ton of plugins available to choose from.</p> <blockquote><p>&#8220;I'm trying to figure out which WordPress membership/subscription plugin is best for me&#8230;I'd like it to be simple to install, and ideally not break the bank (under $100/year would be great). All I want is for people to be able to create accounts on my website, become &#8220;subscribers&#8221; for a week, month, three months, etc with different prices, and have access to certain content while their subscriptions are running. I don't need tiers&#8230; every subscription gets the same content, but the price is different based on length (longer subscriptions will receive discounts). Is there a simple plugin you'd recommend for this?&#8221;</p></blockquote> <p>Even in this really short email, the person has told me a lot about what they want. And they're right, this is pretty simple. What they want is the same content protection, but paid in different intervals. Something like this&#8230;</p> <p><img class="aligncenter size-large wp-image-52979" src="" alt="" width="1024" height="437" srcset=" 1024w, 600w, 300w, 768w, 1536w, 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></p> <h2>It's all about the buyer's intention</h2> <p>In this kind of membership site, the content is the same per plan. What changes is the commitment of the buyer. If they only expect to use the site for a week, why pay more? And if they can get away with figuring out what they want to read in a month's time, why pay more. It really is a simple membership site.</p> <p>And while they don't mention what payment gateways they need support for, it's likely Stripe or PayPal, and the good news is that you can support both. Again, this is important because buyers can sometimes have strong preferences of how they pay for their membership plans. I saw one site lose 30% of its transactions when it removed PayPal from the payment options.</p> <p><img class="aligncenter size-large wp-image-52980" src="" alt="" width="1024" height="672" srcset=" 1024w, 600w, 300w, 768w, 1536w, 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></p> <h2>Protecting Content is Easy with Restrict Content Pro</h2> <p>There are a lot of membership plugins out there when you're building something like this on WordPress. But when it comes to a simple membership site, few are as easy to use as <a href="">Restrict Content Pro.</a> Here's how you protect content, in one of two ways.</p> <p>First, you can protect tons of content simply by doing it at the post category level. You find this screen by heading to Posts &gt; Categories and clicking on one of them.</p> <p><img class="aligncenter size-large wp-image-52981" src="" alt="" width="1024" height="997" srcset=" 1024w, 600w, 300w, 768w, 1536w, 1730w" sizes="(max-width: 1024px) 100vw, 1024px" /></p> <p>That's as easy as it gets. Notice I checked all the plans, since every plan gets access to this content. Additionally, I checked the &#8220;paid only&#8221; checkbox to make sure only paying subscribers get access.</p> <p>The other way to protect content is on a post by post basis. It works when you write something and maybe it's a page, or it's outside of any of the categories you have. And you can do it by clicking on the radio button that is for &#8220;any paid membership,&#8221; which is what I would recommend in this case. Or click the next radio button that allows you to choose specific plans.</p> <p><img class="aligncenter size-large wp-image-52982" src="" alt="" width="1024" height="507" srcset=" 1024w, 600w, 300w, 768w, 1536w, 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></p> <p>Either way, you've created a membership site that protects content in a few clicks by using <a href="">Restrict Content Pro</a>.</p> <h2>The Best Part is the Price</h2> <p>You'll recall that the first part of the request was to create a simple membership site with a membership plugin that wouldn't break the bank. And while there are a couple of free membership plugins that are pretty good. This one does exactly what the customer needs in the least amount of clicks. And does so under budget. Remember, they wanted to keep it under $100.</p> <p><img class="aligncenter size-large wp-image-52983" src="" alt="" width="1024" height="851" srcset=" 1024w, 600w, 300w, 768w, 1536w, 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></p> <p>That Personal Plan is exactly what's needed, and it's $99 (March 2020).</p> <h2>Conclusion: RCP is Great for a Simple Membership Site</h2> <p>As you've seen here, the simplicity of the product goes a long way for solving this particular need. You may have a more complex membership site, but for simple ones, Restrict Content Pro is perfect. Among it's many available features at the $99 level, the 13 additional fee add-ons provide:</p> <ul> <li>Download Monitor Integration</li> <li>MailChimp Integration</li> <li>EasyDigital Downloads Integration</li> <li>User Imports (CSV)</li> <li>Strong Password Support</li> <li>Support for</li> </ul> <p>People use <a href="">Restrict Content Pro (RCP)</a> every day to build a variety of kinds of membership sites &#8211; from blogs with protected content to association membership sites, to private online communities, to buying clubs. If you're building a simple membership site and you want to do it quickly, without a lot of stress, this product will work well for you!</p> <p>And some free advice. <a href="">The best place to host membership sites (and eCommerce sites) is Nexcess</a>.</p> <p>The post <a rel="nofollow" href="">Creating a Simple Membership Site with Restrict Content Pro</a> appeared first on <a rel="nofollow" href="">Chris Lema</a>.</p> text/html 2020-03-10T12:00:06+01:00 A Better Planet OptimizePress Review – The Ultimate WordPress Landing Page Builder text/html 2020-03-09T21:54:52+01:00 A Better Planet Digging into Deep Work <p>My college major was <em>Industrial &amp; Systems Engineering</em>. I was trained to analyze systems and adjust them to seek optimal outcomes.</p> <p>I don&#8217;t work on industrial applications, but the greatest system I have access to today, where I have direct control, and the capability to have an enormous impact, is my own system of <em>how I work</em>.</p> <p>I realize now that I&#8217;ve gone years with limited stints of deep work. I have waded in the shallows, exhaustively, for the vast majority of my work efforts &#8212; constantly shifting from one work arena to another, rarely giving my mind time to properly engage an important task.</p> <p><a href="">Cal Newport</a> won&#8217;t blow your mind with the definition of deep work itself &#8212; which is pretty self explanatory. What I like is, within <a href="">his book</a>, he both makes the case for deep work, and also establishes example routines for sensible, achievable levels of deep work (while leaving the door open for more extreme variations).</p> <p>My own deep work, I realize in retrospect, has usually been either deadline or panic driven. Unmissable deadlines (self set or otherwise) or panic work sessions in rapid bursts of hard-spent energy (almost always at non-ideal times, like late at night or a weekend) have been my primary avenues of deep work. I can do better! Deep work is something I should be accomplishing in my regular routine.</p> <h3 id="excuses-to-work-shallow">Excuses to work shallow</h3> <p>I use social media for work. It has, in no small part, been the responsible venue for my ability to create multiple brands that turned into spheres of influence, income streams, and new friendships.</p> <p>But my ever-present engagement with these platforms is not effective for helping me grow &#8212; either those brands, or in my own work capacity. They are still useful, but they are not necessary to be fully immersed.</p> <p>I can do better work for myself, my clients, and those same social audiences, if I tone down how I interact with social media (primarily Twitter).</p> <p>My default work &#8220;break&#8221; has long been to pop open Twitter and see what&#8217;s happening, which then sometimes can translate back into content that I put out via newsletter, analysis, conversations, etc. But for a long time now, the payoff in what Twitter creates via serendipity is not worth the cost: significant distraction from what&#8217;s important for me to accomplish.</p> <p>Newport&#8217;s book doesn&#8217;t just focus on social media, though it&#8217;s absolutely a key platform for distraction and common reason people avoid deep work. He also talks about the regular ebb and flow of most businesses, and how many are structured in a way to prevent deep work. I have done this in my own work, in how I (poorly, often) balance between three different work endeavors.</p> <p>I have already made several adjustments over the past year or two in how I work. Something led me to read this book, after all. I already acknowledged I needed change, and have experimented. It was a start. Now, my aim is to execute with a better plan, and not haphazard experiments.</p> <p>In response to what I&#8217;ve taken away from this book, I&#8217;m making personal changes which, I hope, I will stick to better by writing them down here <img src="" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p> <h3 id="changes-on-social-media-usage">Changes on social media usage</h3> <p>I&#8217;ve deleted Twitter from my phone. I manage my personal account and two brand accounts &#8212; all of which are active. I felt a sense of abandonment within about 10 minutes, not being able to read my timeline.</p> <p>I know myself. My problem isn&#8217;t that sharing is distracting, it&#8217;s reading (primarily on my phone) that&#8217;s distracting. So I&#8217;m tweeting still, but using Buffer to maintain my social posting, limiting my ability to engage by phone.</p> <p>Now, if I&#8217;m to engage in other things (checking notifications, reading my timeline), I have to purposefully open the app on a desktop, and have a work purpose to do so (much like I&#8217;ve somewhat achieved with email). I do have legitimate work purposes to do this, so it&#8217;s still an important part of what I do, but this should create significantly more balance and barriers in my social interactions.</p> <h3 id="changes-on-chat-management">Changes on chat management</h3> <p>As a remote worker, chat can eat into my day like nothing else. In the web landscape, I use Slack to talk to customers and friends. For SkyVerge, we use it for company chat. For crypto, I use Telegram to talk to friends, other traders, and other relevant contacts for things like my podcast.</p> <p>All of these options for chat take away from deep work opportunities, and introduce plenty of variables that increase the probability my day gets sidetracked. And I know very well how to give into them.</p> <p>I manage thousands of online relationships. Many of these are important. Cumulatively, they should <em>not</em> take over my life.</p> <p>Over the past year, I&#8217;ve gotten better about limiting my chat usage in Slack, but I&#8217;m very good at replacing one bad habit with another. I transitioned some of these broader big-group chats into just as distracting small-group chats.</p> <p>Chat groups for me are a huge distraction. They are important, but they need better management.</p> <ul> <li>I keep chat apps closed on my desktop unless I need to send a message or have a planned session for managing chat. It&#8217;s never casually open.</li> <li>I turned off all notifications for Telegram (crypto stuff is not a priority communication channel and needs should be relegated to leisure time).</li> <li>I only enable Slack notifications for work-sensitive channels, and only via direct mentions and DMs.</li> <li>I quietly removed myself from many, many chats that don&#8217;t meet my primary goals.</li> </ul> <h3 id="tracking-my-habits-better">Tracking my habits better</h3> <p><a href=""><img data-attachment-id="2751" data-permalink="" data-orig-file=";ssl=1" data-orig-size="1242,2208" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="tally-app" data-image-description="" data-medium-file=";ssl=1" data-large-file=";ssl=1" class="alignright size-medium wp-image-2751" src=";ssl=1" alt="" width="400" height="711" srcset=";ssl=1 400w,;ssl=1 1200w,;ssl=1 84w,;ssl=1 768w,;ssl=1 864w,;ssl=1 1152w,;ssl=1 1242w" sizes="(max-width: 400px) 100vw, 400px" data-recalc-dims="1" /></a>I&#8217;m tracking things using the <a href="">Tally</a> app. I&#8217;ve been doing this all year, but I added a category for <em>deep work</em> tracked by hours in a week. I haven&#8217;t yet set a target (an option inside Tally) as I want to see what I tend toward naturally. I&#8217;m hopeful I can get at least two hours per day; Newport advises that 4 is a pretty high bar for most workers who have a significant amount of shallow work required.</p> <p>I&#8217;m already using Tally to track other things:</p> <ul> <li>Physical things: Tracking workouts per month, coffee drinks per day (just to know), alcoholic beverages per week, standing work hours per week, how many times per month I&#8217;m later than my goal dropping my kids off at daycare.</li> <li>Knowledge things: Books per year, good reading sessions per week (the bible, something where I am enriched by reading, etc), personal blog posts per year, and now deep work hours per week.</li> </ul> <p>I like Tally because it&#8217;s easy to use and offers a good overview of how I&#8217;m accomplishing what I aim to accomplish. It offers a dose of reality to my ambitions.</p> <p>Newport logs his deep work hours via tick marks on a paper near his computer. I know through my 70 or so days of Tally-ing that Tally gets the same job done for me: personal drive and satisfaction in ticking the boxes and seeing my progress (or accountability in lack thereof).</p> <h3 id="time-logging-and-schedule-blocking">Time logging and schedule blocking</h3> <p>I&#8217;ve been using <a href="">Toggl</a> to track the time I bill to SkyVerge, where I contract regularly. I have other categories (I tracked how many hours I spent working toward my new partnership for Post Status, for example). But I haven&#8217;t been a great time tracker for other work &#8212; especially shallow work.</p> <p>Two of my most productive friends &#8212; <a href="">Syed Balkhi</a> and <a href="">Brian Richards</a> &#8212; have recommended detailed time blocking to me. Cal Newport also recommends it in his book, via planning sessions of both shallow work obligations (email, data entry, admin stuff) and deep work routines (write long form content, research an important project, write code, etc).</p> <p>I need to divide and conquer my week amongst three focus areas: <a href="">SkyVerge</a>, <a href="">Post Status</a>, and <a href="">Ledger Status</a>. These three focus areas are not equitable distributions, but if I don&#8217;t time block them, it&#8217;s easy for me to spend more time than I intend in an area I shouldn&#8217;t.</p> <p>If I plan my week through detailed time blocking, and then blend this with time tracking, I can better know both my plan and my execution.</p> <p>Newport explains a nice hack on this as well: he understands that a schedule can change. He describes the process where he evolves his time blocks as it inevitably changes during a day or week. It accepts that adaptations can be made while maintaining a commitment to blocking time.</p> <p>I know this will be hard for me. I&#8217;ve tried it before (but without allowing for block-evolution). I look forward to trying this method, which may require I shift from a calendar centric method to old fashioned pen and paper as he recommends.</p> <h3 id="saying-no">Saying no</h3> <p>I say, &#8220;yes&#8221; too often. It usually leads to later saying, &#8220;I&#8217;m sorry.&#8221;</p> <p>I love saying, &#8220;Yes!&#8221; And I don&#8217;t want to stop saying it. I just want to start saying yes to the things I love saying yes to, and saying no, ruthlessly, to everything else.</p> <p>I get so many inbound contacts: via website contact forms, email, Twitter, Slack, chat, wherever. All the time. I&#8217;m pretty good at ignoring the least of these. I&#8217;m pretty good, unfortunately, at ignoring the more important ones too &#8212; particularly through email. Because I&#8217;ve been very bad about managing chat well, I have too often ignored more important asynchronous communication.</p> <p>I want to say yes to things like:</p> <ul> <li>Building small websites for friends or organizations it would benefit enormously</li> <li>Helping mentor or consult someone in my industry who seeks my advice and has great potential</li> <li>Volunteering in my community, for my kids&#8217; activities, or for my church</li> </ul> <p>I must say no much, much more than I do now. No to synchronous requests, and no to things that I know don&#8217;t fit the bill for accomplishing my goals.</p> <p>One of the things Newport did that I&#8217;m absolutely following through on is to establish more friction in cold outreach channels (like my contact form). I want someone to really want to get my attention before I give it my attention. Not because I want to be rude, but because I want to be great for the things I prioritize as my yesses.</p> <h3 id="a-deep-work-benchmark">A deep work benchmark</h3> <p>Systems can be stochastic or deterministic. The way we work is a stochastic system: our work is subject to many variables and probable outcomes as a result of choices made along the way.</p> <p>How we implement our system of work will give us a greater probability to do more high quality work.</p> <p>I&#8217;ve been on a journey to better my work. What Deep Work has helped clarify for me is that <em>deep work</em> can be a difference maker in actually bettering that work.</p> <p>If I prioritize working deeply, I can accomplish several of my goals (things I want to optimize for):</p> <ul> <li>Do better work across multiple disciplines</li> <li>Effectively balance multiple business endeavors</li> <li>Get more stuff done that matters over a long period, rather than just get done what matters near term</li> <li>Keep work at work and have better presence with my family</li> </ul> <p>I use to manage by using &#8220;10 to 2 time&#8221; &#8212; late night deep work sessions to make up for a day in the shallows. Now? I have two kids. I&#8217;m too exhausted for that. I have to have a better system.</p> <p>Newport&#8217;s book covers a lot of things I didn&#8217;t talk about here. His book helped clarify how to go about my work in a systematic way that gives me a higher probability of achieving my goals.</p> <p>If you feel like you&#8217;re consistently in the shallow end of your work potential, <a href="">give it a read</a>.</p> <p>I&#8217;ll try and keep you updated on the evolution of my work systems. Meaningful blogging, after all, is one of my goals. Now if you&#8217;ll excuse me, I have to go, because I&#8217;m excited to tap this button for my first logged hour of deep work.</p> <p><a rel="nofollow" href="">Digging into Deep Work</a> is a post by <a rel="nofollow" href="">Brian Krogsgard</a>. If you enjoyed it, please consider leaving a comment.</p> text/html 2020-03-09T19:02:57+01:00 A Better Planet Booknetic: WordPress Appointments & Booking in a Box text/html 2020-03-04T14:05:09+01:00 A Better Planet Privacy is Hard: Analytics, Revisited <p>In a previous post, I talked a bit about Fathom Analytics and what a fan I was of the service when it first launched. Now that a few months have passed and the product has further evolved, I wanted to revisit the service and share a few things that I like about it. You can read everything I had to say about the plugin in my original post. The purpose of this one, however, is to provide a little...</p> <p><a href="" rel="nofollow">Source</a></p> text/html 2020-01-30T13:03:26+01:00 A Better Planet bbPress 2.6.4 is out! <p>bbPress 2.6.4 is a security release, and fixes <a href=";milestone=2.6.4">8 total issues</a> reported by our amazing, patient, and vigilant community members:</p> <ul><li>Fixes an obscure security issue with BuddyPress Group Forums, allowing Group Members to save Topics to invalid Forum IDs</li><li>Fixes performance degradation for 2.5 database schemas</li><li>Fixes a few typos</li><li>Fixes some debug notices</li><li>Fixes user email changes using the wrong API</li><li>Improves compatibility with PHP 7.2 and higher</li></ul> <p class="has-text-color has-background has-very-dark-gray-color has-luminous-vivid-amber-background-color">Special thanks to Yuvraj Dighe for his responsible disclosure of the BuddyPress Group Forums bug over at <a href="">HackerOne</a>. Thank you for helping improve bbPress. <img src="" alt="👍" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p> <p class="has-text-color has-background has-very-dark-gray-color has-very-light-gray-background-color">Work continues on improving bbPress 2.6 while also doing a bit more clean-up for 2.7. <img src="" alt="🧹" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p> <p style="background-color:#b9eb80" class="has-text-color has-background has-very-dark-gray-color">Expect for the next minor release (bbPress 2.6.5) to be released sometime before March 1. <img src="" alt="🐝" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p> text/html 2020-01-21T18:06:19+01:00 A Better Planet Creating a Block-based Theme Using Block Templates A text/html 2020-01-03T21:36:11+01:00 A Better Planet BuddyPress 5.1.2 Security Release <p><a href="">BuddyPress 5.1.2</a> is now available. This is a security release. All BuddyPress installations are strongly encouraged to upgrade as soon as possible.</p> <p>The 5.1.2 release addresses one security issue:</p> <ul><li>Certain REST API requests could result in the exposure of private data. Discovered and reported independently by <a href="">Petter Walbø Johnsgård</a> and <a href="">Jacek Suski</a>.</li></ul> <p>The vulnerability was reported privately to the BuddyPress team, in accordance with&nbsp;<a href="">WordPress’s security policies</a>. Our thanks to the reporters for practicing coordinated disclosure.</p> <p>For complete details, visit the&nbsp;<a href="">5.1.2 changelog</a>.</p> <p>Update to BuddyPress 5.1.2 today in your WordPress Dashboard, or by&nbsp;<a href="">downloading from the plugin repository</a>.</p> text/html 2019-09-07T23:21:25+01:00 A Better Planet Taking GPL’d code proprietary… text/html 2019-01-21T15:56:04+01:00 A Better Planet 2018 year in review <p>Since 2012, I have written a year-in-review post to detail and share highlights and challenges of the previous year. So as is tradition, here is my review of 2018.</p> <p>Previous year in review posts: <a href="">2012</a> | <a href="">2013</a> | <a href="">2014</a> | <a href="">2015</a> | <a href="">2016</a> | <a href="">2017</a></p> <p>In all, 2018 was an incredibly successful year for me and my company, <a href="">Sandhills Development</a>. We had some great achievements that expanded the team, grew our revenue and profit, acquired a new product, sold two plugin products, branched out into a new market and industry, and matured as a company. We also, however, had some significant challenges that were perhaps some of the hardest yet. I&#8217;d like to share some details about each.</p> <p class="has-large-font-size">Team growth</p> <p>When Sandhills Development first started, I had no intention of having a large team and was very reluctant to ever grow the company to more than 5-8 people. Through the growth of our products, however, it has been necessary to increase the size of our team to fill ever-growing resource needs. At first I was leery to allow the team to expand beyond what I felt I could directly manage but over time I welcomed the challenges that are involved with doing so. </p> <p>Today we are at 19 full time employees and one part time / variable time contractor on the software side of the business, and two full time and two part time helpers in the brewery. We&#8217;re preparing to bring on 2-3 more on the software side in the near term.</p> <p>In March, 2018, we welcomed Tyler Lau full time to our marketing and administration team.</p> <p>In May, 2018, we welcomed Daniel Goldak to our Easy Digital Downloads support team.</p> <p>In May, 2018, we welcomed David Sherlock as a variable time contractor to our Easy Digital Downloads support team.</p> <p>In August, 2018, we hired Jeordyn Hensly to help with retail sales in the brewery. Her role transitioned to brewing assistant and bar tender by October.</p> <p>In August, 2018, we hired Jacob Unruh to work on the production side (brewing, packaging, cleaning) of the brewery. </p> <p>In September, 2018, we welcomed Mihai Joldis to our Easy Digital Downloads and Restrict Content Pro support teams.</p> <p>In October, 2018, we welcomed Mandy Jones to our marketing team.</p> <p>In October, 2018, we welcomed Tunbosun Ayinla to our AffiliateWP development team.</p> <p>In October, 2018, we welcomed Phil Derksen to Sandhills Development as a partner and product lead.</p> <p>Each person that has joined us has been an incredible asset to the team and I&#8217;m proud and honored to have each of them working with us.</p> <figure class="wp-block-image"><img src="" alt="" class="wp-image-100595" srcset=" 1024w, 480w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Sandhills Development team (Mihai not present), September 2018</figcaption></figure> <p>In the next two-four weeks we plan to on-board three or even four new team members in various roles.</p> <p class="has-large-font-size">Sales and acquisitions</p> <p>For the third and fourth time in recent years, I sold two of my earlier plugin products to new owners in 2018. These were products that had tremendous amounts of potential but were falling by the wayside under my control.</p> <p>In February I <a href="">sold Fullscreen Background Images to Scott Deluzio</a>. This was one of my earlier products and one of my favorites for a long time. I think what I liked most about it was its simplicity and single purpose. It&#8217;s easy for plugins to grow beyond their original scope and become something far and away from the original intention. Fullscreen Background Images was a plugin that always stayed true to its original purpose and I really loved that.</p> <p>In October I sold <a href="">Simple Google Maps Shortcode</a> to Gordon at Web Factory. This was another of my favorite plugins that I relished the simplicity of. It literally did one thing and one thing only: register a shortcode that displayed a map of any address. </p> <p>Both of these plugins had a lot of potential for doing much more but managing them on top of our other projects was beyond my capacity, so I decided to sell off both plugins.</p> <p><a href="">In 2017</a>, when we closed the extension marketplace for Easy Digital Downloads, we purchased a large number of plugins from 3rd party developers and brought those plugins under our own management. That was my first experience negotiating purchase deals of that nature. This year I had another first: negotiating an acquisition and merger with another company.</p> <p>On October 1, 2018, Sandhills Development acquired <a href="">WP Simple Pay</a> through a merger.</p> <p>As we have grown over the years, I knew there was a distinct possibility large acquisitions would be in my future, either as the entity being acquired or the entity doing the acquiring. I&#8217;ve had a number of potential acquisition discussions over the years, mostly from parties interested in purchasing Easy Digital Downloads, but this was the first time I was on the other side of the table for a product worth more than $500,000.</p> <p>I had been considering the possibility of purchasing another company / product for some time but had never landed on any definite targets. The acquisition of WP Simple Pay landed unexpectedly but was ultimately a perfect fit for everyone involved so discussions did not take long.</p> <p>In May, <a href="">Phil Derksen</a>, the founder and owner of WP Simple Pay, approached me with a quick email:</p> <figure class="wp-block-image"><img src="" alt="" class="wp-image-100612" srcset=" 710w, 480w, 300w" sizes="(max-width: 710px) 100vw, 710px" /></figure> <p>Ironically, that email was sent a few minutes after we concluded a podcast / webinar episode on the topic of selling WordPress product businesses.</p> <p>Phil went on to tell me how he felt he&#8217;d grown WP Simple Pay as far as he could solo and was ready to be part of a larger team. His options were to either build a team or join an existing team. Phil and I have known each other for close to ten years (we met very early on in both of our WordPress careers) and we&#8217;ve always gotten along great. We share a lot of values and ideals, both in our personal lives and in the way we build products.</p> <p>We quickly agreed that WP Simple Pay and Sandhills Development could be a great fit, so we moved on to discussing ways to make a merger or acquisition a reality. There were a few possible avenues on the table:</p> <ol><li>Sandhills Development could purchase WP Simple Pay outright, assuming full ownership of the product, and then employ Phil</li><li>Phil could sell WP Simple Pay to Sandhills Development and then move on to do something else entirely</li><li>Phil could transfer ownership of WP Simple Pay to Sandhills Development in exchange for cash and/or equity in the larger company</li></ol> <p>In the end we decided on the 3rd option. Phil was given a piece of equity in Sandhills Development in exchange for Sandhills Development assuming ownership of WP Simple Pay.</p> <p>WP Simple Pay was incredibly attractive to me for a number of reasons.</p> <p>The first was that it was led by someone I&#8217;d known and respected for a long time. Anytime you work closely with someone, you will get to know them really well. Ideally you get along great with the people you work with. Knowing that Phil and I already had a good relationship meant there was very little worry about culture and personality fit.</p> <p>The second reason was that WP Simple Pay was already a successful product bringing in ~$25,000 / month with good profit margins. That meant the product was already paying for itself while being operated by a solo founder. With a few additional resources, it won&#8217;t be difficult to grow it to $30,000 and beyond.</p> <p>The third aspect of WP Simple Pay I found attractive as a prospective acquisition was its position in the eCommerce ecosystem. It was successfully serving a niche of customers that neither Restrict Content Pro nor Easy Digital Downloads were fulfilling well, mostly due to the nature of those products and their complexity. By adding WP Simple Pay to our product portfolio, we are able to attract another customer segment, expanding our potential reach.</p> <p class="has-large-font-size">Revenue</p> <p>Since writing my first year-end review in 2012, we have grown our revenue each and every year. In 2018 we continued that trend with an overall increase of 21.47% with a total income of $2,747,500. This was an increase of ~$500,000 over 2017 with a profit increase of 96.65%. </p> <p>Of the $2.7, our break down between projects was roughly:</p> <ul><li>AffiliateWP: $1,170,405</li><li>Easy Digital Downloads: $900,609</li><li>Restrict Content Pro: $396,192</li><li>Sugar Calendar: $11,644</li><li>WP Simple Pay (Oct &#8211; Dec): $74,205</li><li>Brewery: $83,367</li><li>Misc (affiliate income, revenue shares, other): $90,346</li></ul> <p>There are a few items I&#8217;d like to go into more depth regarding revenue.</p> <p>First, AffiliateWP became our first product to independently surpass a million in revenue in a single year. This was a milestone I was exceptionally pleased with and is a testament to the product we&#8217;ve built and the team behind it. Along with being our largest revenue generator, it&#8217;s also still one of the least difficult products to maintain and support. It&#8217;s incredibly stable and due to it&#8217;s stability and high volume, it operates on a ~30% profit margin.</p> <p>The excess cash flow generated by AffiliateWP has enabled a level of flexibility for us that has been immensely valuable. It has permitted us to take risks, devote team members to new projects, and put efforts into places we wouldn&#8217;t have otherwise.</p> <p>We have extensive plans for AffiliateWP in the next year and I&#8217;m really excited to share more information about those soon.</p> <p>Second, Easy Digital Downloads saw a decline in revenue for the first time. Over the course of 2018, our average monthly revenue dropped from $73,500 to $70,500, with a peak at $83,000 and a bottom of $60,600. Note: I have excluded November from these averages due to the significant fluctuations caused by our annual Black Friday sale. In the first half of the year, we averaged $73,700 per month and in the second half of the year that average had dropped to $66,500. </p> <p>This decline, while it may not look too terribly drastic, was excruciating to watch and deal with. On average we had a net operating loss of $10,000 every month for six months in a row. Out of the 12 months in 2018, seven operated at a loss ranging from $2,500 up to $20,800. At the end of 2018 we did manage to turn a small profit for Easy Digital Downloads but that was largely due to the influx of funds the annual Black Friday sale brings us.</p> <p>There are a lot of factors we have considered as possible reasons for the decline in Easy Digital Download&#8217;s revenue, but they are mainly guesses. We&#8217;ve been unable to nail down one or even many definite causes. A few potential reasons include:</p> <ul><li>Natural age of a product. It&#8217;s possible we&#8217;ve simply hit our peak, though I don&#8217;t believe this.</li><li>We unintentionally out-priced our average customer. This is quite possible.</li><li>We face tougher competition than ever before. This is definitely a factor.</li><li>Something changed (such as traffic sources) but we haven&#8217;t identified it yet.</li><li>Business owners got spooked by GDPR and other stricter regulations of online businesses.</li><li> We have not succeeded well enough at updating our product offering to hold the interest and value of business owners.</li></ul> <p>While we are unsure of what 2019 holds for EDD&#8217;s revenue, we are fully committed to it and do believe firmly that we&#8217;ll be able to continue to grow above and beyond what we&#8217;ve done thus far.</p> <p>The fourth item I&#8217;d like to cover is the $74,205 we added through WP Simple Pay. By acquiring a mature product, instead of building from scratch, we significantly increased the rate of revenue growth. Of course we also incurred the necessary expense to acquire the product and its team (Phil Derksen). Due to how the merger / acquisition was done, however, the cost had no direct impact on our cash flow nor cash reserves.</p> <p>The $74,205 revenue that WP Simple Pay added was purely from October 1 to December 31st. With an average of $24,735 in monthly sales, WP Simple Pay will have a significant impact on our 2019 sales.</p> <p>The fifth part of our revenue I want to mention in more depth is the $83,367 we earned through Sandhills Brewing. Last year my brother and I seriously entered into an effort to open a microbrewery in our hometown, and we succeeded. The brewery began operating in February, 2018, and opened to the public at the end of April, 2018. We started at $1,181.11 in sales our first month of operation and finished the year with ~$13,000 in December.</p> <p>Note, some of the reported revenue for the brewery is from investment from Sandhills Development.</p> <p>I&#8217;ll share more on the brewery below.</p> <p>The final aspect of our revenue I would like to touch on is profitability. In <a href="">2017</a> I stated that one of my goals was to maintain the sustainable profitability that we had achieved. In 2018 I&#8217;m pleased to say we were able to hold strong and operated at a 19% profit margin.</p> <p>This profitability gave us the flexibility to grow, invest, and plan for the future .</p> <p class="has-large-font-size">Content marketing</p> <p>I began my career in WordPress with blogging. Early on I wrote multitudes of posts and articles, ranging from tutorials to opinion pieces to product launches. Writing content was integral to everything I did.</p> <p>As the company grew, however, it became more and more challenging for me to write as frequently as I would have liked and my publication rate dwindled to almost zero. In the last year for example, I&#8217;ve published less than 10 articles.</p> <p>Content marketing is something we&#8217;ve struggled with as a company for a long time. We never quite managed to figure out how to consistently produce high quality content on a consistent schedule. We tried again and again but never succeeded.</p> <p>That is until this last year. At the end of 2017 we put together a content plan for 2018 that included planned content for several months at a time with specific people assigned to write the content. This worked really well but was still a struggle because it required everyone to find time in their already busy schedules to write the content. What it did, however, was pave the way and lay the foundation for a dedicated position in our team for the first time: content writer.</p> <p>We hired Mandy Jones towards the end of summer to come on as our dedicated writer. This worked really well, not only because it raised the bar for how much content we could push out but because it also significantly lightened the load of the rest of the team that had been working extra hard to produce the content previously.</p> <p>For the first time in a long while, we were able to publish consistent, high quality content across multiple brands.</p> <p>Hiring a dedicated writer was an excellent reminder of how hiring the right person for the right role can have a significantly positive impact on a teams&#8217; performance and work load.</p> <p>Along with the content marketing efforts we pushed forward in 2018, we finally for the first time also managed to establish a real marketing department led both by Kyle Maurer and Lisa Gibson. As a developer at my core, I&#8217;ve always struggled with many aspects of effective marketing so it was never a part of the company I felt comfortable managing nor creating. </p> <p>One of the beautiful aspects of building a team is seeing first hand the skills and values each team member can bring to the table. In 2018 Lisa and Kyle clearly demonstrated their marketing skills and made it clear how much value we could add by having a full-fledged marketing program.</p> <p>Today we have four full-time team members working in marketing. By the end of the year I expect we will add one or two more. </p> <p class="has-large-font-size">Product updates</p> <p>As usual, there are a number of significant updates surrounding each of our products throughout the year, and I&#8217;d like to share a few with you for each.</p> <p class="has-medium-font-size">Easy Digital Downloads</p> <p>At the <a href="">end of 2017</a> we announced a plan for significant updates to Easy Digital Downloads in order to solve some large, overwhelming issues left over from poor early decisions. We originally estimated that we would be able to finish and release the update within the first six months of 2018.</p> <p>Obviously that release did not happen as we are still yet to release 3.0 and it&#8217;s now more than a year past our original announcement. There are a bunch of reasons the release has taken longer, but the primary reason is that the project was simply way larger of an undertaking than we had originally estimated. It was extensive enough that it has taken more than a year of very active development by half a dozen developers to get it near beta ready.</p> <p>We are now anticipating a beta being ready in the next 1-3 months and we are working to provide for frequent updates on our <a href="">development blog</a>.</p> <p>Since we&#8217;ve spent so much of our development resources on the development of 3.0, many other areas of Easy Digital Downloads slowed down in 2018, though never to a stand still. We now have a better team than ever before and we&#8217;re able to keep continued focus on numerous areas of the product at all times.</p> <p>As mentioned above in the revenue section, Easy Digital Downloads did see its first decline in sales in 2018. We tackled the problem from a lot of different angles, but two of the most visible are what we did with pricing (yes we changed them again).</p> <p><a href="">In June</a> we launched a new pricing model that introduced &#8220;access passes&#8221; for extensions. These were effectively memberships that granted access to certain extensions. The lower memberships granted access to more basic or standard extensions and the higher memberships granted access to the more advanced extensions. This is the direction we have planned to take Easy Digital Downloads for several years. We originally launched EDD with what came to be called the &#8220;extension model&#8221;, where advanced features are sold as separate plugins, each requiring their own purchase.</p> <p>Over the years we collected extensive evidence to suggest that a la carte extension sales is not a great experience and, oftentimes, is too challenging and/or overwhelming for customers. The access passes we introduced in June were our solution to the problem by neatly packaging all of the extensions into a tiered membership setup.</p> <p>Except it didn&#8217;t work.</p> <p>We had already seen the model work wonderfully for AffiliateWP and Restrict Content Pro so we really expected the same model to work for Easy Digital Downloads too. After launching the new model, however, our sales continued to decline and they dropped enough that we were seriously concerned that we had just damaged them even further.</p> <p>Ultimately we came to a conclusion on why the memberships didn&#8217;t work for Easy Digital Downloads: we had out-priced our average customer. Even though the membership options were offered at a significant discount over purchasing extensions individually, the price tag continued to scare people off. At least that is what we believed.</p> <p>On <a href="">August 1</a> we lowered the prices for extension passes. That change was difficult to make and not without challenges, but it appeared to have worked:</p> <figure class="wp-block-image"><img src="" alt="" class="wp-image-100565" srcset=" 797w, 480w, 300w, 768w" sizes="(max-width: 797px) 100vw, 797px" /><figcaption>Aug 1 &#8211; Oct 31 compared to previous three months</figcaption></figure> <p>We are still at a lower monthly revenue than at the beginning of 2018 but we are continuing to see improvements.</p> <p class="has-medium-font-size">Restrict Content Pro</p> <p>In 2018 we were able to raise RCP&#8217;s revenue by more than $60,000 over the previous year. We were able to achieve this by continuing development and significantly upping our marketing efforts for the platform.</p> <p>Along with the content marketing mentioned above, we also leaned heavily on re-targeting advertising, both of which helped push the needle.</p> <p>The main focus in 2018 for RCP was the completion of 3.0, which, like EDD 3.0, is a significant architecture adjustment with a re-designed database structure that improves performance and opens the gates for a large number of major features we&#8217;ve wanted to build for a long time. The previous database design prohibited a lot of important features.</p> <p>Restrict Content Pro 3.0 beta was <a href="">released last week</a> and so far has been running smoothly. We&#8217;ll give it a couple more weeks before finalizing the release.</p> <p>It took nearly a year to complete the 3.0 update, in part because of its size and complexity and in part because we had an unexpected team departure that took its toll on the project. More on that below. </p> <p class="has-medium-font-size">Sugar Calendar</p> <p>On March 13, 2018, I <a href="">announced</a> a new website and development focus for Sugar Calendar. The plan was to do with Sugar Calendar what we did with <a href="">Restrict Content Pro</a>, and that is still the plan that we are working on completing.</p> <p>Due to a number of reasons, some in our control and some outside of our control, the development and release of the new Sugar Calendar has taken significantly longer than we had intended. Our intentions originally were to have the new version and a series of add-ons released in six months or less from the time of that announcement. That, sadly, has not happened, and we&#8217;re not proud of it.</p> <p>Our communication of the delays that have occurred have also been less than stellar, and for that I want to apologize to each and every one of our customers.</p> <p>The good news, however, is that we are still absolutely dedicated to finishing the project and I can now say with much more confidence that we are getting close.</p> <p>We currently plan to release the beta of the new version on, or very close to, February 5, 2019.</p> <p class="has-medium-font-size">AffiliateWP</p> <p>AffiliateWP continues to be the most reliable and feature-rich affiliate marketing plugin available for WordPress. Through extensive integrations and wide support for all of the main eCommerce, membership, and form plugins, AffiliateWP has continued to grow and thrive.</p> <p>We hit two milestones in 2018 for AffiliateWP. First, we broke the $2,000,000 mark in earnings, and second, we broke $1,000,000 in sales in a single year.</p> <p>2018 saw an increase of $273,930 in revenue over 2017, with several months breaking $100,000 in earnings.</p> <p>Even though we&#8217;ve had great success with AffiliateWP, we feel we&#8217;ve only scratched the surface and there&#8217;s so much more we want to build. We have extensive plans for the next 9-12 months and we can&#8217;t wait to share some of them. The first major initiative we&#8217;re working on is expected to launch into beta in the first or second quarter of 2019. </p> <p class="has-medium-font-size">SellBird</p> <p>We have been teasing <a href="">SellBird</a> for more than two years now. While it is still not ready to show you, I am thrilled to say we have made a <em>lot </em>of&nbsp;progress on the platform and are nearing our first beta phases.</p> <p>SellBird has been one of the most interesting and definitely most challenging projects we&#8217;ve worked on. We&#8217;ve always had a general idea of what we wanted to build, but determining exactly how the detailed aspects of the platform behave really eluded us for quite some time.</p> <p>The first year of working on SellBird was mostly us just picking around without really creating anything. A shotgun approach if you will. The second year of SellBird began to see a more specific target that permitted it to start taking shape. Finally after more than two years, we have a very clear goal for the project and progress is moving forward nicely. </p> <p class="has-medium-font-size">WP Simple Pay</p> <p>As mentioned above, WP Simple Pay joined the Sandhills family in October. Being our first experience bringing an existing, thriving product under our control, there has been some adjustment periods and elements of the merge that have gone slower than we&#8217;d like, but overall it&#8217;s gone very well.</p> <p>We have worked to increase the development and marketing resources on the project and have been working towards merging support systems.</p> <p>Towards the end of November we released the first major update for WP Simple Pay after adding more developer resources to the project. The 3.3 update introduced some significant new features that really helped extend the platform and give customers more control over the display and behavior of their payment forms.</p> <p>In the next 12 months we will continue to devote significant developer and marketing resources to push the product further. </p> <p class="has-large-font-size">Sandhills Brewing</p> <p>Anyone that has spent any amount of time with me in person, at conferences or other events, likely knows that I have a deep seated love for locally made craft beer. About three years ago my brother and I made a commitment to opening our own brewery as a passion project.</p> <p>In February, 2018, we managed to complete the licensing process and were able to legally begin producing beer at <a href="">Sandhills&nbsp;Brewing</a>.</p> <p>The brewery was a passion for both my brother and I and something we&#8217;d wanted to do for a long time. We both, however, had full time career positions running our respective companies that consumed the vast majority of our time. While neither of us knows what the long term future holds, we did both know that we were not ready to leave the digital world behind, so opening the brewery was in no way a career change. It was, instead, a way for us to realize several of our deep passions, namely creating specialty beers and building positive changes in our communities. </p> <p>When we first opened to the public in April, we were set up to serve free samples and sell beer in sealed containers that customers could take home with them. We operated out of a <em>very </em>rough and minimal warehouse space for six months. It was very much a minimum viable product, but it worked.</p> <p>We used the warehouse and the to-go sales to slowly fund the construction of our first taproom, which we managed to open at the end of October. The taproom is a place customers can come and sit down to enjoy a beer with friends and family. It was created to be a comfortable space designed for casual conversations and low key enjoyment of the wide array of beer styles we produce. </p> <ul class="wp-block-gallery columns-3 is-cropped"><li class="blocks-gallery-item"><figure><img src="" alt="" data-id="100580" data-link="" class="wp-image-100580" srcset=" 768w, 270w, 225w, 1200w" sizes="(max-width: 768px) 100vw, 768px" /></figure></li><li class="blocks-gallery-item"><figure><img src="" alt="" data-id="100581" data-link="" class="wp-image-100581" srcset=" 768w, 270w, 225w, 1200w" sizes="(max-width: 768px) 100vw, 768px" /></figure></li><li class="blocks-gallery-item"><figure><img src="" alt="" data-id="100582" data-link="" class="wp-image-100582" srcset=" 1024w, 480w, 300w, 768w, 1200w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>The taproom space we opened in October</figcaption></figure></li><li class="blocks-gallery-item"><figure><img src="" alt="" data-id="100583" data-link="" class="wp-image-100583" srcset=" 768w, 270w, 225w" sizes="(max-width: 768px) 100vw, 768px" /></figure></li><li class="blocks-gallery-item"><figure><img src="" alt="" data-id="100584" data-link="" class="wp-image-100584" srcset=" 1024w, 480w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>Re-arranging barrels</figcaption></figure></li><li class="blocks-gallery-item"><figure><img src="" alt="" data-id="100585" data-link="" class="wp-image-100585" srcset=" 1024w, 480w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>My brother fixing a leaky barrel</figcaption></figure></li><li class="blocks-gallery-item"><figure><img src="" alt="" data-id="100586" data-link="" class="wp-image-100586" srcset=" 1024w, 480w, 300w, 768w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>One of our first canning runs</figcaption></figure></li><li class="blocks-gallery-item"><figure><img src="" alt="" data-id="100587" data-link="" class="wp-image-100587" srcset=" 1024w, 480w, 300w, 768w, 1200w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption>The original warehouse</figcaption></figure></li></ul> <p>The beer world is heavily regulated and nothing moves quickly. Anything that involves the state or federal government is measured in timelines of weeks and months, not hours or days, much less minutes or milliseconds. After building companies in the digital space where it&#8217;s easy to get antsy when a file download takes a few extra seconds, it was both agonizingly painful and refreshing to work within an industry that expects less rapid turn around times.</p> <p>As I have detailed a few times before, I have faced a few significant mental challenges in the last few years while building Sandhills Development. Most recently I struggled with severe burnout. I found myself completely incapacitated and unable to find any joy in digital work. I was, and am, immensely proud of what we&#8217;d built and the team I&#8217;d assembled, but the day-to-day work of maintaining the company was draining my will to be in front of a screen.</p> <p>The brewery ended up being exactly what I needed to re-discover my passion for WordPress and the web. I effectively took a six-eight month break from the digital world to build the brewery with my brother and in doing so, re-discovered my love for the web and the products we have been building as a team.</p> <p>Along with helping me re-find a passion for the web, the brewery has given me an inordinate number of experiences that I&#8217;ve been able to turn into valuable lessons for the software side. </p> <p>Sandhills Brewing is the brewery that WordPress built. Without the success of our WordPress-based products, Sandhills Brewing would have never happened. With that, if anyone reading this is a beer fan and finds themselves in Hutchinson or Mission, KS, come visit our spaces!</p> <p>Interested in following along with our brewery journey? Follow along through our <a href="">website</a> or <a href="">Instagram</a>.</p> <p class="has-large-font-size">My personal trials and triumphs</p> <p>I&#8217;m writing this while Molly and I prepare to welcome our third daughter to the world and it reminds me of how fortunate we are to have the family, friends, and support that we do.</p> <p>On the personal side, 2018 was largely defined by three major experiences.</p> <p><strong>Opening&nbsp;Sandhills&nbsp;Brewing</strong></p> <p>First, as described above, my brother and I succeeded with a goal we&#8217;d had for a long time: open a brewery. Brewing has been a passion of ours since ~2012 and we have both yearned for side-projects that include more direct connection to the physical world and the communities in which we live. Sandhills Brewing fulfilled both criteria superbly. It has given us a chance to work with our hands (we did the majority of our own construction, remodeling, and equipment installations ourselves) and it has enabled us to have a more direct connection with the people in our community.</p> <p>Within less than a month of opening, the brewery&#8217;s taproom quickly became a gathering spot for many groups of friends and families. Each weekend, when the taproom is open, we see people come in, sit, and enjoy the space and beers we&#8217;ve created. They smile, laugh, and cheer. Unlike in the digital world, nearly every interaction we have with customers is a positive experience. We are part of their celebration and it&#8217;s immediately obvious how distinct the juxtaposition is to our digital interactions, which typically revolve around a problem that needs fixed.</p> <p>For the first time ever, I have a sense of purpose and belonging in my local community. It used to only be a place I lived, now it&#8217;s a place I feel a part of and one I want to help thrive. And we&#8217;re now working on repeating the process by opening our second brewery and taproom in Kansas City.</p> <p><strong>The&nbsp;Sandhill&nbsp;Prairie&nbsp;Farm&nbsp;wild&nbsp;fire</strong></p> <p>The second major experience occurred in March, right as we were in the middle of getting the brewery&#8217;s production up and running. Prairie fires are not terribly uncommon in Kansas, like other drier parts of the world. While we&#8217;ve had close-calls with fires in the past, my family has never dealt with the destruction of a direct hit. That is until <a href="">March 14, 2018</a>, when a prairie fire lit by an arsonist tore through my parent&#8217;s property, destroying everything in its path. Everyone that was in the house when the fire approached escaped unharmed, though it was an incredibly close call for my father who rushed to turn on sprinklers and hoses to try and save the house. The fire moved so quickly and within minutes it was on all sides of the property, cutting off the road and escape route. He was forced to drive across pastures to escape.</p> <p>That was quite possibly the longest, most trialing day of my life, but also one that strengthened family and neighborly bonds. The number of people that came to our aid to help with cleanup and restoration was deeply humbling. When I first got the call from my dad to tell me about the approaching fire, I immediately jumped into our team&#8217;s Slack channel and left a simple message:</p> <blockquote class="wp-block-quote"><p>Emergency. Parent&#8217;s property on fire.</p></blockquote> <p>My team did not hesitate and immediately understood what that meant. Aside from the obvious, it was clear and known that I would be unavailable for an undetermined amount of time. The whole team stepped up and took care of everything, many of them even offering to drive across the country to come help with cleanup.</p> <p>I&#8217;ve never been more grateful nor proud to work with my team.</p> <p>The fire, while terrible, gave me a greater appreciation for the relationships we build. Ultimately family and friends, and the bonds we nurture with those people, are more important than anything else we can possibly build.</p> <p><strong>Possible&nbsp;acquisitions&nbsp;and&nbsp;a&nbsp;team&nbsp;departure</strong></p> <p>The third major experience of 2018 was perhaps a culmination of four others: struggling with mental burnout, building the brewery, the wild fire, and then losing one of my most senior team members.</p> <p>In my <a href="">2017 review</a> I described the experience of re-discovering my role within my own company. I continued to struggle with motivation throughout much of 2018, even though I now had a better idea of where I fit in. Building the brewery gave me new purpose and was an opportunity to take a much-needed mental break. The wildfire helped me recognize the importance of relationships and the power and strength of a great team. Then two more series of events happened.</p> <p>In the course of two-to-three months, I was approached by not one, not two, not three, but five different companies interested in potentially acquiring all or part of Sandhills Development. These conversations, while not entirely new to me, came at a time I was feeling vulnerable but also potentially motivated to sell. I&#8217;d just gone through a traumatic family experience that made me relish the idea of having fewer business obligations, I was actively involved in building the brewery, and I was mentally burnt out from the digital world. Each of those made me consider the possibility of walking away more than ever before.</p> <p>In the middle of those conversations, a metaphorical bomb dropped.</p> <p>John Parris, one of my longest-term team members, a shareholding partner, most valuable contributors, and a great friend, called to tell me he needed to leave the company.</p> <p>Early on in John and I&#8217;s working relationship, we were sitting in a brewery enjoying dinner and a beer when I asked him what he <em>really</em> wanted to do in the next few years. I&#8217;ll never forget what he told me: </p> <blockquote class="wp-block-quote"><p>I want to run your company while you go make beer.</p></blockquote> <p>It took a lot of guts to say something like that to the CEO of the company, and I <em>loved</em>&nbsp;it. It showed me that John was confident, motivated, and as determined as I was to build Sandhills Development into something great.</p> <p>John was a huge supporter of the brewery efforts, not just because he wanted me to follow my passions but because he understood the importance of diversifying our revenue streams, and he saw tremendous value in the company building physical presences that have the potential to outlast each of us.</p> <p>I believed John to be one of my most solid pillars in the company, but then he left unexpectedly, and it rattled me to the core.</p> <p>Like me, John had been struggling with mental burnout and was needing a change of scenery. That just so happened to coincide with a large WordPress company&#8217;s recent acquisition creating a position for John that landed in his lap unexpectedly. It was too good of an opportunity for him to turn down.</p> <p>The month proceeding his phone call to me became one of the most difficult I&#8217;ve ever experienced in my leadership tenure for this company. I felt lost, angry, betrayed, and overcome with an overwhelming sense that I had lost control of my company. I was tormented with the thought that my efforts to build the brewery and my struggles with mental burnout had culminated in the initial signs of the demise of my company. I barely slept, worrying that I would be forced to choose between leading the brewery and leading the digital team.</p> <p>I began to consider more than ever the possibility of selling my company. Being blindsided with the departure of a team member that I believed would never leave, made me really wonder &#8220;what if?&#8221;. I knew that selling my company would afford me enough financial freedom to not need to worry about money. I also knew that selling my company would give me unbridled freedom to pursue passions I haven&#8217;t been able to focus on.</p> <p>I also knew, however, that selling the company at this stage would leave me with an overwhelming sense of abandonment. I felt that I had just been abandoned by my partner so how could I do the same to the rest of my team? While acquisition conversations never got as far as discussing a price, the moment I recognized that selling would cause me to abandon my team, I knew my way forward, and it did not involve selling the company.</p> <p>I don&#8217;t blame John for needing to leave and I&#8217;m proud to have worked alongside him. I&#8217;m thrilled for him to have found a new way to exercise his skills and passions and wish him nothing but the best. Ultimately I recognized that it was likely my own inaction that lit the fire leading to his departure.</p> <p>Recognizing where my own failings or inaction caused John to leave has given me tremendous motivation to prevent that from happening again. In retrospect it was probably an event that needed to happen eventually in order to drive the necessary changes within Sandhills Development as a company.</p> <p class="has-large-font-size">2019 and beyond</p> <p>2018 had significant wins for several of our products and from a revenue / profit perspective and, while not everything went great, I feel I&#8217;ve learned and grown more as a CEO this past year than ever before. Based on what we&#8217;ve learned as a team and what we already have in motion, I suspect 2019 will be our best year yet.</p> <p>We try to avoid setting major year-long goals and instead to focus on smaller, more short-term goals that we can more easily measure and achieve. We do, however, hope to achieve the following in 2019:</p> <ol><li>Raise overall revenue to $3,500,000</li><li>Release Sugar Calendar 2.0 and a series of Pro add-ons that helps raise its revenue to $20,000 / month</li><li>Launch and begin generating revenue through it</li><li>Hire between 3 &#8211; 6 new team members</li><li>Launch an affiliate payouts service for AffiliateWP</li><li>Formalize more of our processes and the company structure / operations</li><li>Continue to increase revenue and expand the platform for each of our products</li></ol> <p>Cheers to years past and those yet to come <img src="" alt="🍻" class="wp-smiley" style="height: 1em; max-height: 1em;" />!</p> <p>The post <a rel="nofollow" href="">2018 year in review</a> appeared first on <a rel="nofollow" href="">Pippins Plugins</a>.</p> text/html 2018-07-23T22:02:18+01:00 A Better Planet Page Links To v3.0 A text/html 2018-01-08T13:00:09+01:00 A Better Planet Constructing The Perfect WordPress Contact Form: 6 Unbreakable Rules <p>You do everything you can to build a website that will lead visitors to conversion. As you study the analytics, you’re excited to see that the user journey you’ve created is being taken by those visitors, time and time again. However, there’s something keeping them from converting. Find out what it is in this advanced contact forms guide.</p> <p>The contact form is a critical part of your visitors’ journey.</p> <p>Even if you’ve effectively sold them on whatever the website has to offer, a contact form could realistically ruin the experience for them if not executed well.</p> <p>Broken buttons, confusing fields, too many steps, a disorganized interface… Heck, even the <a href="" target="_blank" rel="noopener noreferrer">placement of the contact form</a> could disrupt the user experience.</p> <p>There’s a lot that can go wrong, and in this article we&#8217;ll be doing our best to educate you on how you can avoid these things.</p> <p>More specifically we&#8217;re giving you our&#8230;</p> <h2>6 Rules For Building the Perfect Contact Form</h2> <p><strong>But hold on, quick PSA first&#8230;</strong></p> <p>Before we go any further, you should know this is an advanced look into the world of WordPress contact forms.</p> <p>If you want a simple introduction, our <a href="" target="_blank" rel="noopener noreferrer">getting started with contact forms</a> post is a great place to start.</p> <p>Then, once you know you need to create more contact forms for your site, the next step is <a href="" target="_blank" rel="noopener noreferrer">choosing the right contact form plugin</a> to make life easier.</p> <p>Once you&#8217;ve done those things we reckon you&#8217;ll be ready and primed for the advanced in-form-ation (heh) that follows.</p> <p><strong>Moving on&#8230;</strong></p> <p>User logins. Membership sign-ups. Email subscriptions. Quote requests. Questionnaires. Support requests. Order and payment forms.</p> <p>There are a bunch of different ways to use contact forms on a WordPress site. What doesn’t change, however, are the rules you must abide by if you want the contact form to perform well.</p> <p>A <a href="" target="_blank" rel="noopener noreferrer">Google eye-tracking study</a> published in 2014 showed that following the most basic usability guidelines for form design will significantly improve the user experience.</p> <p>Specifically, when a contact form abides by all the rules, 78% of users can complete and submit them in a single try. When a contact form violates those rules, however, only 42% are able to do it in one attempt.</p> <p>Curious to know what those rules are? Then keep reading.</p> <h2>Rule #1: Focus on Alignment</h2> <p>As you’ll see in some of the other rules here, people are often concerned with the length of contact forms, which is what often leads to bad design choices.</p> <p>Take the matter of alignment, for instance.</p> <p>You might see a form like this one on the BrainTraffic website and think, “Hmmm… but isn’t that a little too long to fill out?”</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - BrainTraffic Alignment" width="600" height="347" /><figcaption class="wp-caption-text">This is just a beautifully constructed contact form on the BrainTraffic website.</figcaption></figure> </div> <p>One way you might think about fixing this “problem” is by shifting the labels to the left-hand side and placing the answer fields on the right.</p> <p>However, UX experts will tell you that’s a major no-no as it compromises the scannability of the form.</p> <p>The same thing applies if you were thinking about placing fields next to each other horizontally.</p> <p>Basically, if you deviate from the label-on-top/field-below-it structure, you’ll create friction within the user experience.</p> <p>Back in 2010, a set of guidelines were issued regarding the design of web forms called “<a href="" target="_blank" rel="noopener noreferrer">Simple but Crucial User Interfaces in the World Wide Web: Introducing 20 Guidelines for Usable Web Form Design</a>” .</p> <p>Google picked those guidelines up in 2014 and put them to the test with an <a href="" target="_blank" rel="noopener noreferrer">eye-tracking study</a>.</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600" src="" alt="Perfect Contact Form - Google Eye Tracking" width="600" height="319" /><figcaption class="wp-caption-text">It&#8217;s clear from this eye-tracking test how much work we&#8217;re putting visitors&#8217; eyes through when we don&#8217;t pay attention to alignment.</figcaption></figure> </div> <p>Among their many findings, they concluded that left-aligned forms with labels placed atop each field resulted in an improved user experience.</p> <p>If you’d like your contact forms to abide by this simple alignment rule, here is what you need to do:</p> <ul> <li>Left-align all labels, form fields, and the main call-to-action button.</li> <li>Never align related fields horizontally. You can structure the form logically, but each question or field needs to be stacked vertically.</li> <li>Any field that has multiple choice questions (with under six options) should be displayed in a vertical list of bullet points or checkboxes, not in a drop-down menu.</li> </ul> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - WPMU DEV Mobile Button" width="337" height="600" /><figcaption class="wp-caption-text">A really nice example of mobile contact form alignment and design from WPMU DEV.</figcaption></figure> </div> <p>Not only is this design great for the user experience, but it will help your site bridge the gap between the desktop and mobile experience (especially important as you work towards updating your sites for <a href="" target="_blank" rel="noopener noreferrer">Google’s mobile-first index</a>).</p> <h2>Rule #2: Include All Relevant Fields</h2> <p>When it comes to designing contact forms, you might think that shorter is better, right?</p> <p>This actually isn’t always the case. What matters most is that you provide users with all necessary and relevant fields.</p> <p>Michael Aagaard, the Senior Conversion Optimizer for Unbounce, gave <a href="" target="_blank" rel="noopener noreferrer">a presentation</a> in 2015 that tackled this very question.</p> <p>He and his team wanted to know what would happen if they shortened this contact form:</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - Unbounce A:B Test 1" width="600" height="316" /><figcaption class="wp-caption-text">Surprisingly, the shorter form did not fare as well as the longer one.</figcaption></figure> </div> <p>As you can see, they removed what they believed to be unnecessary fields in order to streamline the process of filling out the form.</p> <p>However, upon concluding the test, they discovered a 14% drop in conversions with the shorter form.</p> <p>Afterward, they studied which fields had the highest and lowest interactions on the contact form.</p> <p>Using the original, longer design, they rearranged those fields and updated the labels to clarify what type of information was needed.</p> <p>They re-ran the test and saw a 19% improvement in leads with the relabeled and reorganized version of the long form:</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - Unbounce A:B Test 2" width="600" height="316" /><figcaption class="wp-caption-text">Unbounce found that the keys to improving the longer contact form were in the labels, not the form length.</figcaption></figure> </div> <p>That’s not always how these tests work out though.</p> <p>Expedia, for example, found that <a href="" target="_blank" rel="noopener noreferrer">there was a field in the contact form</a> for “Company” that was confusing customers.</p> <p>It was optional, but users didn’t necessarily understand that and, in turn, filled out the wrong information which eventually led to their purchase being declined.</p> <p>When Expedia realized the issue, they removed the field and saw an additional $12 million in revenue the following year.</p> <p>I would suggest that, when building your own contact form, start with the basic fields as QuickBooks has done here:</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - QuickBooks Fields" width="600" height="460" /><figcaption class="wp-caption-text">Only the most necessary fields are included when signing up for QuickBooks.</figcaption></figure> </div> <p>If you find that conversions aren’t tying out with expectations, study the analytics and see if you can determine which fields are stopping users up from completing the form.</p> <h2>Rule #3: Simplify Input</h2> <p>Regardless of whether your users engage with your contact form using a desktop or mobile device, or whether or not they need assistive technology to help them do it, the form should be equipped to simplify the input process.</p> <p>Here are some techniques you should be aware of:</p> <p><b>Tabbing</b><br /> For desktop users and those with accessibility issues, make sure your contact form has a <a href="" target="_blank" rel="noopener noreferrer">logical tabbing order</a> enabled.</p> <p><b>Input Masks</b><br /> Rather than force users to guess how you want certain fields formatted, you can <a href="" target="_blank" rel="noopener noreferrer">code them with input masks</a> that automatically format them as the user types.</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - Social Design House Format" width="600" height="333" /><figcaption class="wp-caption-text">An example of what an input mask looks like from the Social Design House website.</figcaption></figure> </div> <p>This type of auto-formatting also leads to fewer clicks (especially if a field like a phone number or credit card is broken into multiple fields) and quicker form completions.</p> <p><b>Input Types</b><br /> <a href="" target="_blank" rel="noopener noreferrer">HTML input types</a> will help users see the right keyboard options as they type on mobile, saving them from having to type everything from scratch (like the “.com” for email).</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - Elluminati Adaptive Keyboard" width="270" height="480" /><figcaption class="wp-caption-text">Watch how the keyboard at the bottom of this Elluminati contact form changes based on the field selected.</figcaption></figure> </div> <p><b>Google Autocomplete</b><br /> Rather than code each field to automatically format per the standards it needs to meet, enable auto-fill with the <a href="" target="_blank" rel="noopener noreferrer">Google Address Autocomplete plugin</a>.</p> <p>Not only will it help you avoid having to deal with misspellings and improperly formatted addresses, it’ll spare your visitors from having to type most of that information out.</p> <p><b>Conditional Logic</b><br /> If you’re worried about the length of your contact form&#8211;especially if it targets different user types and fulfills various purposes&#8211;you can use conditional logic to keep it short.</p> <p>Once the user selects their particular “condition”, only then will the relevant parts of the form be exposed.</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - Pixflow Expanded Form" width="480" height="300" /><figcaption class="wp-caption-text">Upon selecting the final field, users are presented additional fields to fill in that are most relevant to their request.</figcaption></figure> </div> <p>Many contact form plugins come with an extension for this. For example, here’s one for <a href="" target="_blank" rel="noopener noreferrer">Forminator</a>.</p> <figure id="attachment_185859" class="wp-caption aligncenter" data-caption="true"><img class="size-full wp-image-185859" src="" alt="Forminator screenshot with conditional logic button" width="600" height="646" /><figcaption class="wp-caption-text">Create forms with conditional logic using Forminator.</figcaption></figure> <p><b>Breadcrumbs</b><br /> <a href="" target="_blank" rel="noopener noreferrer">A breadcrumb or progress bar</a> for a contact form isn’t necessarily about simplifying the process of filling out a form.</p> <p>However, it does help encourage users to finish it as the remaining steps are clearly defined.</p> <p>Once again, here&#8217;s an example of a progress bar using Forminator&#8217;s Pagination element:</p> <p style="text-align: left;"><figure class="wp-caption center" data-caption="true"><video loop muted autoplay playsinline class='wpmud-html5-video'><source src="" type="video/webm"><source src="" type="video/mp4"></video><figcaption class="wp-caption-text">Add a progress bar to forms to help users navigate more easily through the form-filling process.</figcaption></figure></p> <h2>Rule #4: Spell Everything Out</h2> <p>While I realize this rule will go against the basic principles behind minimalism, it’s one that you should pay close attention to so you can avoid unnecessarily frustrating your visitors.</p> <p>Let me explain: You have a contact form that looks simple enough.</p> <p>Your users fill it out based on what the labels suggest and they hit the submission button.</p> <p>Then they receive that ugly red message: “You didn’t do it right! Go back, fix the form, and resubmit!”</p> <p>You’ve likely encountered this as a user and you know how frustrating it can be, especially if some of the information you inputted drops out when the error is thrown.</p> <p>So, rather than leave users guessing about what needs to be fixed and how, don’t let it get to that point.</p> <p><strong>Spell everything out along the way:</strong></p> <ul> <li>Provide field focus (especially on mobile) so users know exactly where they are in the process of filling out a form.</li> <li>Write out any formatting requirements if you’re not using input masks to auto-format fields.</li> <li>Explicitly state when a field is “Optional” (use the word, not the red asterisk).</li> <li>Give users the ability to show or hide the password field as they enter it.</li> <li>Show an error message as soon as the user has engaged with a field. Don’t wait until the very end to do it.</li> </ul> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - Hubspot Error Messages" width="600" height="359" /><figcaption class="wp-caption-text">Hubspot shows the right way to handle error messages in a contact form.</figcaption></figure> </div> <p>In the aforementioned Google eye-tracking study, they followed up with users who took the test and found that a lack of formatting was often specified as a complaint.</p> <p>Google suggests providing clear guidelines throughout the form as well as highly visible error messages. In addition, these labels shouldn’t just be in a standard red font.</p> <p>They should be outlined, colored, and bolded.</p> <h2>Rule #5: Stay Away from Hints</h2> <p>Hint text in a contact form looks like this:</p> <div class="wpdui-pic-regular "> <figure class="wp-caption alignnone" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - Target Field" width="600" height="295" /><figcaption class="wp-caption-text">While Target has fixed some of the problems associated with using hint text in form fields, it still might not be enough for users with accessibility issues.</figcaption></figure> </div> <p>See how Target places the labels within the field? In some contact forms, those labels/hints simply disappear when a user clicks on a field.</p> <p>Target handles this a little differently and instead shifts the label to the top of the field box (see “email address”).</p> <p>Regardless of how this is handled, usability experts&#8211;like the <a href="" target="_blank" rel="noopener noreferrer">Nielsen Norman Group</a>&#8211;will tell you that this is a bad design practice because:</p> <ul> <li>This is problematic for users that are multi-tasking, get distracted, or too quickly tab into the next field. When the hint disappears, users have to back out of the field in order to rediscover what is needed.</li> <li>Hints that disappear also prohibit users from going back over a form to check their work or to fix an error without deleting the response completely to see what’s underneath.</li> <li>The lighter grey text used for placeholder hints isn’t ideal for easy reading.</li> <li>Fields with hint text can be confused for fields that have already had data filled in, leaving users to skip them, submit the form, and receive an error message.</li> <li>Some screen reader tools aren’t capable of reading placeholder hint text.</li> </ul> <p>According to the NNG, users find empty fields more attractive than those that contain hint text.</p> <p>While it may make your forms look longer to place those labels or descriptors above the field, it’ll improve usability.</p> <h2>Rule #6: Look at Your Buttons</h2> <p>WPMU DEV already has a great <a href="" target="_blank" rel="noopener noreferrer">guide to designing better buttons</a>, so I’m not going to rehash that. Instead, I want to focus on the few things you can do to improve your contact form buttons.</p> <p>For starters, always align the primary CTA with the form fields, even if it doesn’t seem logical.</p> <p>For instance, if you have a “Next” and “Back” button, “Next” should appear on the far left as it’s the action most users are going to take.</p> <p>Also, try not to use “Reset”, “Clear”, or “Cancel” buttons. Many users get to the bottom of a form and automatically click on the first button they see, thinking it’s the submission button.</p> <p>If they lose all their answers by erroneously hitting the wrong button, you may find them unwilling to re-submit.</p> <p>In this <a href="" target="_blank" rel="noopener noreferrer">A/B test from Unbounce</a>, they found that value-driven copy (even if longer) was more successful in converting users.</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - Unbounce A:B Test 3" width="600" height="381" /><figcaption class="wp-caption-text">The CTA text may be longer, but users responded much more positively to the value-driven message.</figcaption></figure> </div> <p>The updated copy received over 31% more conversions than the original message.</p> <p>Finally, <a href="" target="_blank" rel="noopener noreferrer">use trust marks</a> around your contact form buttons when it makes sense.</p> <p>The CoSchedule statement about no credit card being required is a nice example of this:</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - CoSchedule Button" width="600" height="352" /><figcaption class="wp-caption-text">Generally, a great-looking form that does a good job of using &#8220;trust mark&#8221; text that encourages users to click without hesitation.</figcaption></figure> </div> <p>But be careful. If you use a trust mark when it’s not needed, it could mislead users into believing they have to hand over sensitive information when that’s not actually the case, as this <a href="" target="_blank" rel="noopener noreferrer">A/B test from Behave</a> demonstrates:</p> <div class="wpdui-pic-regular "> <figure class="wp-caption aligncenter" data-caption="true"><img class="attachment-600x600 size-600x600" src="" alt="Perfect Contact Form - Behave A:B Test" width="600" height="146" /><figcaption class="wp-caption-text">You&#8217;d assume the TRUSTe trust mark would help increase conversions, but that&#8217;s not so in this case.</figcaption></figure> </div> <p>Version B received almost 13% more submissions than Version A as the security seal led users to believe they’d eventually have to submit payment or other sensitive information through the website.</p> <h2>Time To Apply The In(Form)ation</h2> <p>Contact forms are not a one-size-fits-all kind of thing.</p> <p>Every website (and business behind the website) has a different goal and, thus, the contact forms within it need to work specifically to help achieve that goal.</p> <p>If you want to properly execute the rules above while working towards those goals, you have two options.</p> <p>You can find a WordPress plugin that will help you <a href="" target="_blank" rel="noopener noreferrer">create a custom WordPress contact form</a> or you can <a href="" target="_blank" rel="noopener noreferrer">build your own</a>.</p> <p>A plugin like WPMU DEV&#8217;s <a href="" target="_blank" rel="noopener noreferrer">Forminator</a> gives you the best of both worlds (and it&#8217;s free!).</p> <p>Install the plugin and choose a template to start with, then build the form to suit your specific needs with a range of powerful customization options and settings.</p> <p>Whatever you decide, just remember that users aren’t necessarily afraid of lengthy contact forms, it’s more about how well you’ve created an experience within the form for them.</p> text/html 2018-01-06T16:55:40+01:00 A Better Planet Vulnerability in phpMyAdmin Requires Immediate Patch A text/html 2016-08-23T14:40:45+01:00 A Better Planet .blog <p>As you may have heard, Automattic <a href="" target="_blank">recently</a> secured the rights to operate the sale and registration of .blog &#8212; a new top-level domain, which is currently in the Sunrise period, where trademark owners can apply.</p> <p><img src="" alt="" width="2080" height="772" class="alignnone size-full wp-image-8259" srcset=" 2080w, 300w, 768w, 680w" sizes="(max-width: 2080px) 100vw, 2080px" /></p> <p>The Landrush period, where anyone can apply for their desired .blog domains, is scheduled for November 2nd, and public launch is expected on November 21st. However, a few select bloggers were granted the possibility to get .blog domains sooner as part of the Founders Program, and I was very lucky to be one of them.</p> <p>Welcome to <strong></strong> &#8212; a new home for my archive of <a href="" target="_blank">almost eight years</a> worth of writing on many topics, including SEO (yeah&#8230;), AWS, Twitter, robotics, Linux, PHP, WordCamps and WordPress.</p> <p>I admit I have neglected this place for a while, haven&#8217;t posted as much as I should have, and I can probably come up with plenty of excuses. But this new domain comes with a little string attached &#8212; I have to write more frequently, which I intend to do, so watch out for fresh thoughts, ideas, tips and hacks, and a lot of WordPress of course.</p> <p>If you&#8217;re looking for your own .blog domain, head over to <a href="" target="_blank"></a> for more information and updates.</p> <h3>More from Konstantin Kovshenin</h3> <ul> <li><a href=";utm_medium=latest_posts&#038;utm_campaign=feed">WordCamp Moscow 2016 Recap</a></a></li> <li><a href=";utm_medium=latest_posts&#038;utm_campaign=feed">What the Queries</a></a></li> <li><a href=";utm_medium=latest_posts&#038;utm_campaign=feed">WordCamp Russia 2015 Recap</a></a></li> <li><a href=";utm_medium=latest_posts&#038;utm_campaign=feed">Capture the Flag / OTA 2015</a></a></li> <li><a href=";utm_medium=latest_posts&#038;utm_campaign=feed">Color Options vs. Decisions in WordPress Themes</a></a></li> </ul> text/html 2015-01-07T14:23:01+01:00 A Better Planet Universal Typography with Tim Brown A text/html 2012-04-17T14:00:15+01:00 A Better Planet How to Fix the Error Establishing a Database Connection in WordPress <p>Are you seeing the &#8216;Error establishing a database connection&#8217; notice on your WordPress website? It is a fatal error that makes your WordPress website inaccessible to the users. </p> <p>This error occurs when WordPress is unable to make a connection to the database. A number of things can affect your WordPress database connection which makes it a bit difficult for beginners to troubleshoot. </p> <p>In this article, we will show you how to easily fix the error establishing a database connection in WordPress. </p> <p><img title="Fixing the database connection error in WordPress" src="" alt="Fixing the database connection error in WordPress" width="550" height="340" class="alignnone size-full wp-image-71579" /></p> <h4>What Causes Error Establishing a Database Connection in WordPress?</h4> <p>The &#8216;Error establishing a database connection&#8217; issue can be caused by incorrect database information in your WordPress settings, corrupt database, or an irresponsive database server. </p> <p><img title="Database connection error in WordPress" src="" alt="Database connection error in WordPress" width="550" height="182" class="alignnone size-full wp-image-71582" /></p> <p>A <a href="" title="Database">database</a> is a software which makes it easy to store, organize, and retrieve data into other software. </p> <p>As a content management system, WordPress uses a database to store all your content and other website data. It then connects to the database each time someone visits your website. </p> <p>WordPress needs the following information for connecting to the database:</p> <ul> <li>Database name</li> <li>Database username</li> <li>Database password</li> <li>Database server</li> </ul> <p>This information is stored in your WordPress configuration file called <a href="" title="wp-config.php">wp-config.php</a>. </p> <p>If any of these items are incorrect, WordPress would fail to connect to your database server, and you&#8217;ll see the &#8216;Error establishing a database connection&#8217; error. </p> <p>It is one of the <a href="" title="40 Most Common WordPress Errors and How to Fix Them">most common WordPress errors</a>. Apart from incorrect credentials, this error can also appear if the database server is down, or the database files are corrupt.</p> <p>Let&#8217;s take a look at how to fix error establishing database connection issue in WordPress with step by step troubleshooting. </p> <h4>1. Check Your WordPress Database Credentials</h4> <p>The most common reason for database connection error in WordPress is incorrect database credentials. If you have recently <a href="" title="How to Move WordPress to a New Host or Server With No Downtime">moved your WordPress site to a new host</a>, then this could be the most likely reason. </p> <p>Your WordPress database credentials are stored in the wp-config.php file. It is the WordPress configuration file that contains important WordPress settings including database information. </p> <p>If you have not edited wp-config.php file before, then take a look at our guide on <a href="" title="How to Edit wp-config.php File in WordPress">how to edit wp-config.php file</a> in WordPress. </p> <p>You&#8217;ll be looking for the following lines in the wp-config.php file. </p> <pre class="brush: php; title: ; notranslate"> // ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define( 'DB_NAME', 'database_name_here' ); /** MySQL database username */ define( 'DB_USER', 'username_here' ); /** MySQL database password */ define( 'DB_PASSWORD', 'password_here' ); /** MySQL hostname */ define( 'DB_HOST', 'localhost' ); </pre> <p>You need to make sure that the information for the database name, username, password, and database host is correct. </p> <p>You can confirm this information from your <a href="" title="How to Choose the Best WordPress Hosting in 2020 (Compared)">WordPress hosting</a> account dashboard. Simply log in to your hosting account and click on MySQL databases under the database section. </p> <p><img title="Database information" src="" alt="Database information" width="550" height="326" class="alignnone size-full wp-image-71556" /></p> <p>This will take you to the database management page in your hosting dashboad. From here, you can find out your database name and the username. </p> <p><img title="Database name and username" src="" alt="Database name and username" width="550" height="201" class="alignnone size-full wp-image-71557" /></p> <p>Below that you will find the database users and links to change the user password. </p> <p><img title="Changing database user password" src="" alt="Changing database user password" width="550" height="174" class="alignnone size-full wp-image-71558" /></p> <p>Once you have confirmed your database name, username, and password, you can change that information in your wp-config.php file if needed. </p> <p>After that, try visiting your website again to see if the database connection error has gone. </p> <p>If you can still see the error, then this means that something else is wrong. Continue reading for more troubleshooting steps. </p> <h4>2. Check Your Database Host Information</h4> <p>If you are confident that your database name, username, and password information is correct, then you may want to make sure that you are using the correct database host information. </p> <p>Most WordPress hosting companies use localhost as your database host. However, some <a href="" title="When Do You Really Need Managed WordPress Hosting? Best Managed WordPress Hosting Compared (2020)">managed WordPress hosting companies</a> use separate servers to host databases. In that case, your database host information will not be localhost. </p> <p>You need to contact your WordPress hosting company to confirm your database host information. </p> <h4>3. Repair WordPress Database</h4> <p>If you are getting a different error on the wp-admin, for instance, something like &#8220;One or more database tables are unavailable. The database may need to be repaired”, then you need to repair your database.</p> <p>You can do this by adding the following line in your wp-config.php file. Make sure to add it just before ‘That’s all, stop editing! Happy blogging’ line wp-config.php.</p> <pre class="brush: php; title: ; notranslate">define('WP_ALLOW_REPAIR', true);</pre> <p>Once you have done that, you can see the settings by visiting this page:</p> <p><img title="Repair WordPress database" src="" alt="Repair WordPress database" width="550" height="291" class="alignnone size-full wp-image-71559" /></p> <p><strong>Note:</strong> the user does not need to be logged in to access the database repair page. Once you are done repairing and optimizing your database, make sure to remove this code from your wp-config.php.</p> <h4>4. Check if Your Database Server is Down</h4> <p>If everything seems to be correct, and WordPress still cannot connect to the database, then your database server (MySQL server) may be down. </p> <p>This could happen due to heavy traffic on a server. Basically, your host server just cannot handle the load (especially when you are on <a href="" title="The Truth About Best Shared WordPress Web Hosting">shared hosting</a>). </p> <p>Your site will get really slow and for some users it may even output the error. So the best thing you should do is get on the phone or live chat with your hosting provider and ask them if your MySQL server is responsive.</p> <p>If you have other websites running on the same server, then you can check those sites to confirm that your SQL server is down.</p> <p>If you do not have any other site on the same hosting account, then simply go to your hosting dashboard and try to access <a href="" title="Beginner’s Guide to WordPress Database Management with phpMyAdmin">phpMyAdmin</a> and connect the database. </p> <p>If you can connect, then we need to verify if your database user has sufficient permission. Create a new file called testconnection.php and paste the following code in it:</p> <pre class="brush: php; title: ; notranslate"> &lt;?php $link = mysqli_connect('localhost', 'username', 'password'); if (!$link) { die('Could not connect: ' . mysqli_error()); } echo 'Connected successfully'; mysqli_close($link); ?&gt; </pre> <p>Make sure to replace the username and password. You can now upload this file to your website and access it via web browser. </p> <p>If the script connected successfully, then it means that your user has sufficient permission, and there is something else that is wrong. </p> <p>Go back to your wp-config file to make sure that everything there is correct (re-scan for typos).</p> <h4>Other Solutions That Have Worked for Users</h4> <p>If the above-mentioned troubleshooting tips failed to fix the database connection error on your website, then you may try these additional steps. </p> <p>Reported by our users, these steps have helped some users resolve the database connection error on their websites. </p> <p><strong>1. Update WordPress Site URL</strong></p> <p>Try updating the WordPress site URL using phpMyAdmin. Simply access phpMyAdmin from your hosting account dashboard, and select your WordPress database. </p> <p><img title="Running SQL in phpMyAdmin" src="" alt="Running SQL in phpMyAdmin" width="550" height="273" class="alignnone size-full wp-image-71588" /></p> <p>After that click on the SQL menu on the top and enter the following MySQL query. </p> <pre class="brush: php; title: ; notranslate"> UPDATE wp_options SET option_value='YOUR_SITE_URL' WHERE option_name='siteurl' </pre> <p>Don&#8217;t forget to provide your own site URL and change wp_options to your own table name as you may have changed the <a href="" title="How to Change the WordPress Database Prefix to Improve Security">WordPress table prefix</a>. </p> <p><strong>2. Rebooting Web Server</strong></p> <p>Users on dedicated servers, local server, and <a href="" title="Do You Really Need a VPS? Best WordPress VPS Hosting Compared – 2020">virtual private servers (VPS)</a> can try rebooting their servers. </p> <p>This will restart your web and database server which may fix some temporary glitches causing the error. </p> <p><strong>3. Ask for help</strong> </p> <p>If everything else fails, then you may need to contact your web hosting company. All good WordPress hosting companies will help you troubleshoot the problem, point you in the right direction, or even fix it for you. </p> <p>You can also <a href="" title="6 Best Places to Hire WordPress Developers">hire WordPress developers</a> from <a title="Codeable" href="" rel="nofollow noopener" target="_blank" >Codeable</a> that can help you fix this issue for reasonable rates. The best part is that these developers are highly-vetted by Codeable team, so you know they can be trusted.</p> <p>We hope this article helped you fix the error establishing a database connection in WordPress. You may also want to see our <a href="" title="Beginner’s Guide to Troubleshooting WordPress Errors (Step by Step)">WordPress troubleshooting guide</a> for tips on resolving WordPress issues on your own. </p> <p>If you liked this article, then please subscribe to our <a href="" title="WPBeginner on YouTube" target="_blank" rel="nofollow">YouTube Channel</a> for WordPress video tutorials. You can also find us on <a href="" title="WPBeginner on Twitter" target="_blank" rel="nofollow">Twitter</a> and <a href="" title="WPBeginner on Facebook" target="_blank" rel="nofollow">Facebook</a>.</p> <p>The post <a rel="nofollow" href="">How to Fix the Error Establishing a Database Connection in WordPress</a> appeared first on <a rel="nofollow" href="">WPBeginner</a>.</p> text/html A Better Planet Blog or Static Page: How to Change the Default Homepage in WordPress text/html A Better Planet Multilingual E-Commerce: How to Achieve Worldwide Sales With WordPress