Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Find It, Write It, or Buy It?

    Find It, Write It, or Buy It?

    When you need to extend WordPress, you have three main choices for how to do it. You can find the code on WordPress.org, you can write the code, or you can buy premium code.

    Which is right depends more on your situation and skills than your space cash.

    Find It

    This is the cheapest, though it can be time consuming. Finding a good plugin or theme on WordPress.org is less a factor of the search function, and more a function of being unable to codify ‘need’ clearly. For example, if you want a slider plugin (no judgement here), there are around 2000 possibilities. Newspaper themes? You’re looking at 70 or so that may fit the bill.

    Finding what you need means you must narrow your search. You have to decide what kind of sliders, or what format of newspaper, you feel is the most important. You want a slider with text overlay? That’s different than one that supports animated images. Newspaper themes don’t always have the same formatting options.

    Once you find the features you want, you still have the headache of reviewing the developer and the code. Oh yes. If you’re installing plugins without looking into the developers or the code, you run a high risk of damaging your site. This isn’t a huge deal for a hobby site, but if you’re trying to make a business or a successful niche site, this can make or break you.

    So. Should you rely on what you find? For the most part, yes. Provided you can vet the code, you’re going to save yourself time, effort, and money. There’s no sense in reinventing the wheel.

    Write It

    This is the most expensive choice. Seriously. Think about how much you get paid a year. Let’s say you make $80k. Divide by two to get $40k. Now. You’re worth about $40 an hour. So if it takes you ten hours to write a plugin or theme, that’s $400. Surprise.

    So why would anyone write their own code? Basically because you cannot find what you’re looking for in a way that meets your requirements, be it security, stability, or functionality. Often you will find very close versions of what you’re looking for, but when the magic bullet is missing, it’s up to you to build it all your own. This is how forks happen, in software, by the way.

    There’s nothing inherently wrong with this, but it requires time and skill you may not have. But should you do it? Yes. If you can’t find what you want, and you know you can write and support the code, this is a perfectly viable option.

    Buy It

    People always seem to not want to do this. And really the only reason I can understand not wanting to buy premium code is that you can’t vet the usability or security until you buy it. That makes freemium code like Yoast SEO or Monster Insights my favourite kind. You can use their free code, see how well it works and if these are people you could work with.

    But when you argue that you shouldn’t have to pay for code, I gesture towards the door and ignore you. Because yes, yes you should. Remember how 10 hours of writing your own code is around $400? Plus ongoing upkeep? Okay, that plugin you want is $60 a year. That means six years of the plugin is the same cost as writing it yourself. Which is a way better deal.

    Should you buy it? Yes! Absolutely yes, buy the plugins but only if you can vet the plugin shop first.

    Wait… You said yes to all three!

    Surprise twist ending!

    Here’s the thing. Every single decision you make has a cost and repercussions. They’ll all cost you time, money, and a bit of a headache no matter what you pick. So the real answer, the one I can’t give you, is what’s worth more to you?

    For me, I will use free if it exists, I’ll write my own if it doesn’t, and I’ll buy premium if they do it so well I’m just whistling dixie.

  • Crypto Mining on Websites Isn’t Evil

    Crypto Mining on Websites Isn’t Evil

    A recent hot button topic in WordPress has been Crypto Mining.

    What is Crypto Mining?

    Mining is a way to use your computer hardware to ‘mine’ for Bitcoin (or whatever cryptocurrency). Cryptocurrency is a digital currency, generated by performing computationally expensive tasks that use a lot of your computer’s processing power. Basically a computer is paid for solving math numbers. This math solving verifies transitions, and effectively runs the cryptocurrency Wall Street.

    Mining is earning money.

    Why is it bad?

    The problem is that you can’t actually do any profitable mining on your laptop. It’s not powerful enough. People have to build out crazy computers dedicated to mining, and those use a lot of power, which means you’ll end up paying more for electricity than it’s worth. Somewhere along the line, people decided to use the power of the crowd to make the money for them, and started to bundle mining tools in their software. uTorrent, for example, did that so every time you used their app, you made them a few thousandths of a penny. With millions of users, they make money and you pay more for electricity.

    Isn’t that illegal?

    Well. No. You agreed to their Terms of Use and guess what got buried in those EULA’s you clicked “I Accept” on? Surprise! Technically this means its legal. Ethical is, of course, a different matter. Mining without reporting your income on your taxes is illegal (surprise again), but the actual mining itself isn’t. But the reason why people say this is unethical is less that people are using your computer to mine, but that you don’t get any of the money from it!

    How did websites get involved?

    People figured out how to embed, via javascript, a mining program in websites as an alternative to those ads no one clicks. While most (if not all) web hosts will kick you off their services for using their servers to mine, this instead uses the computers of site visitors to mine. Which brings us back to the part where your laptop (or worse – phone) is being used to mine without your knowledge or real permission. Because in the case of the javascript, most aren’t asking you to opt in. All the visitors make thousandths of a coin for the website, all without knowing (except maybe wondering why the website is a little slow).

    It’s THAT illegal?

    Apparently not. Which is why I recommend you install and use an adblocker. I currently use Ghostery, which is an add-on for your browsers. It stops most bad actors from being loaded if they’re tracking you, but it doesn’t block all javascript. Which yeah, it shouldn’t! You need javascript for the modern web to run.

    Instead, you could block bad javascript, which I do via jsBlacklist – a Safari extension. I’m sure it exists for other things, and my friend Jason has a Javascript Blacklist of all the naughty miners and services he knows.

    Amusingly, Showtime’s website was mining, and we’re not yet sure how or why. It was removed quickly.

    Is there a good way to use this on my website?

    If you absolutely must, I recommend an approach like AuthedMine. This legit enforces opt in. But check with your web host first to make sure it doesn’t violate their terms. And above all, make sure people know what they’re agreeing to.

  • Dynamic Amazon Associates

    Dynamic Amazon Associates

    I preface this with a note that there are actually a lot of WordPress plugins that purport to do this.

    Stable, Topical, Content

    Sometimes a blog is just a blog, and you write what you write. Other times you have a site that covers an ever expanding, diverse plethora of topics. When you have topical content that can be easily identified and codified, the game changes. You no longer are forced to rely on generic ads, you can pick and chose what works best for your specific content.

    There are two general ways to achieve this. The first way is adding a specific ad to each page, manually, and the second is figuring out how to automate it.

    Using an API

    Amazon has a Product Advertising API which gives developers access to the entire product catalog, which can let you programmatically determine what links to call and when. Like a lot of Amazon APIs, it’s not exactly written in low-geek levels of usage. This is my constant complaint about Amazon and their services: they were not written to be easily understood.

    Thankfully, unlike my experience with making a custom Alexa skill, I did not actually have to invent the wheel. This time there is a fully functional, if poorly documented, Amazon Product Adverstising Library based on PHP REST and SOAP using the Product Advertising API..

    A ‘Simple’ Application

    The API is best installed via composer, which isn’t my favorite method. Nothing against composer, it’s great to pull down a library and it’s dependancies. My issues with it are that people don’t properly flag their archives so even if you use --prefer-dist on your build, you still get all the tests and documentation and that annoys me.

    Anyway. Use composer, get the files, and then you can use it to call Amazon searches and build links:

    <?php
    include_once( 'vendor/autoload.php' );
    
    use ApaiIO\Configuration\GenericConfiguration;
    use ApaiIO\Operations\Search;
    use ApaiIO\ApaiIO;
    
    $conf = new GenericConfiguration();
    $client = new \GuzzleHttp\Client();
    $request = new \ApaiIO\Request\GuzzleRequest($client);
    
    $conf
        ->setCountry( 'com' )
        ->setAccessKey( AWS_API_KEY )
        ->setSecretKey( AWS_API_SECRET_KEY )
        ->setAssociateTag( AWS_ASSOCIATE_TAG )
        ->setRequest( $request );
    $apaiIO = new ApaiIO( $conf );
    
    $search = new Search();
    $search->setCategory( 'DVD' );
    $search->setActor( 'Lucy Lawless' );
    $search->setKeywords( 'Xena' );
    
    $formattedResponse = $apaiIO->runOperation( $search );
    
    var_dump( $formattedResponse );
    

    Obviously you don’t ‘var_dump’ for real, but it’s a good way to get an idea of what kind of data you’ll be getting back. You can also reformat the output by changing the response transformer. For example, if you want an array, you can add this to your $conf setting:

      ->setResponseTransformer( new \ApaiIO\ResponseTransformer\XmlToArray() )
    

    Customizing Keywords

    Of course not everyone wants every search result to be about a warrior princess. Pity, but that’s the world for you. These three aspects are the ones most people will care about:

    $search->setCategory( 'DVD' );
    $search->setActor( 'Lucy Lawless' );
    $search->setKeywords( 'Xena' );
    

    All of that data was actually saved in the post, so I wrote my code to extract it. That is the actual magic, though. On pages for characters, we had their actors. On pages for shows, we had the show title and genre. Using that, we were able to logically extract the information to generate the appropriate ads.

    Why Not a Plugin?

    I did mention there were plugins that do this. The problem was that I needed to mess with that customization so much. I had to hand code in the logic (which was not perfect) to show the ‘right’ links on the right pages. No plugin met all my needs nor permitted enough customization in the right ways.

  • The Curious Case of a Comatose Cloud

    The Curious Case of a Comatose Cloud

    The summary here is that remotely hosting SVGs caused a massive slowdown.

    Isn’t the Cloud Magic?

    Nope. Well. No. It is totally magic, in that they’re great for large files and are an inexpensive storage alternative. But the cloud is, at the end of the day, just another server out there in the world, holding your data. Unless that cloud server is behind a CDN, you may not see a great deal of speed improvements on your site.

    And in my case, it didn’t.

    Diagnosing the Problem

    In building out a dev site with Tracy (LilJimmi), we noticed certain pages were really slow to load. 35 seconds slow. That’s unacceptable. I compared it to the live site, and it was faster, but some specific pages were still incredibly slow. What pages? The L Word for the most part. And as we inched closer to being done, I said “I’m going to fix this speed stuff before the weekend!” because you can’t go-live on a slow site. You just can’t.

    Once I was home, I fired up a local site, installed Query Monitor, and had a serious sit down with everything.

    It Wasn’t What I Thought

    My initial thought, the one I ruminated on during my bike ride home, was that it was the database queries. Most shows have one or two queer characters, but The L Word has 60 right now. While I may joke about wanting nine more, it’s a weird situation where I need to get the number of characters on the show without knowing the number of characters on the show. My assumption was that it was my calculation loop that caused the issue. That I was querying the queers too many times.

    Turned out it wasn’t (just) the number of characters, it was the number of tags.

    How It Got So Slow

    Most of the issue is my fault. Every single tag has a custom image associated with it. These images are stored remotely, in the cloud, and called as part of the design. The issue was that when calling the images I ran a check “Is the service available?” and if not, it would stop. When you make one or two calls, it’s no big deal. When you make a couple hundred, it adds up.

    The L Word had 2 icons per 60 characters, and then 15 tags, and then 30 more icons.

    Remote Get Is Slow

    I used wp_remote_get to process my images, and it was taking between .1 and .4 seconds per image. That adds up. At first I simplified my check-if-exists routine and more than halved the time to load from 35 to 15 seconds. But in order to drop the page back to 1 second-ish load times, I had to put the images local again. No matter what I did, if I loaded them remotely the best I could get was a 13 second page page load.

    Sometimes, local is better.

    What’s the moral?

    Obviously the moral is test before you rollout. Which we certainly did! By using Query Monitor, I was able to narrow down the speed for the database queries as well as the speed for all the HTTP requests. In doing so, I lost a CDN but gained speed. I’m trying to figure out how to speed up the CDN, maybe by finding a different front-end proxy, but right now I’ll keep using it for the large files like videos rather than the hundred small ones.

    I think it it’s worth it.

  • FacetWP: Spinning While Updating

    FacetWP: Spinning While Updating

    When you use FacetWP you can do some cool things like change the ‘count’ output of a page. Using the function facetwp_display() you can add facetwp_display( 'counts' ) to your page title, and then a boring old archive title goes from “List of Characters (2022)” to “List of Characters (1-24 of 2022)”

    But… What if you could do more?

    What Could Be More?

    If you have a lot of data, sometimes a page can load and FacetWP spins while it collects everything in it’s wee javascripty brain. When that happens, you have a cognitive moment of “What?” And in order not to lose a user, you want to indicate, somehow, that an action is happening. A spinning icon is, I think, a great way to do that.

    So with that in mind, I want to do this:

    List of Characters showing a spinning icon for the number

    And I did.

    The Code

    This needs javascript. I used some logic from the FacetWP documentation and some memories about how you can replace text with javascript and came up with this:

    (function($) {
    	$(document).on('facetwp-refresh', function() {
    		$('.facetwp-count').html('<i class="fa fa-spinner fa-pulse fa-fw"></i><span class="sr-only">Loading...</span>');
    	});
        
        $(document).on('facetwp-loaded', function() {
    	   $('.facetwp-count').html('');
    	});
        
    })(jQuery);
    

    Then I slap it into my PHP code like so:

    $count_posts = facetwp_display( 'counts' );
    
    the_archive_title( '<h1 class="facetwp-page-title page-title">' . $title, ' (' . $count_posts . '<span class="facetwp-count"></span>)</h1>' );
    

    The content for $count_posts shows nothing while it’s loading, so the check for facetwp-loaded will handle it perfectly.

  • Alternate Symbols

    Alternate Symbols

    I like to remotely host my SVGs and then call them in my code. For the most part, this works well, and I wrote out some basic code to check if they’re defined and accessible before displaying.

    But what if you wanted your fallback to be a font-icon?

    And remember, you want your code to be DRY as a bone. So no repeating chunks of code all over the place, please and thank you.

    The Code

    There is but ONE requirement here. You have to define HALFELF_SYMBOLICONS_PATH as the path to your SVGs. In my case, mine is something like http://my-cool-icons.objects-us-west-1.dream.io/svgs/ because I’m using DreamObjects for them. Any cloud host works great for this, mind you.

    function halfelf_symbols( $svg = 'square.svg', $fontawesome = 'fa-square' ) {	
    
    	$icon = '<i class="fa ' . $fontawesome . '" aria-hidden="true"></i>';
    
    	if ( defined( 'HALFELF_SYMBOLICONS_PATH' ) ) {
    		$response      = wp_remote_get( HALFELF_SYMBOLICONS_PATH );
    		$response_code = wp_remote_retrieve_response_code( $response );
    		
    		if ( $response_code == '200' ) {
    			$get_svg      = wp_remote_get( LP_SYMBOLICONS_PATH . $svg );
    			$response_svg = wp_remote_retrieve_response_code( $get_svg );
    			$icon         = ( $response_svg == '200' )? $get_svg['body'] : 'square.svg';
    		}
    	}
    
    	return $icon;
    }
    

    This checks for the existence of the server used and if the actual icon exists before it sets things.

    Usage Example

    In my code, I define it like this:

    $icon  = halfelf_symbols( 'users.svg', 'fa-users' );
    $title = '<span role="img" aria-label="users" title="Users" class="TEMPLATE users">' . $icon . '</span>';
    

    This sets the icon and then calls the span which will help make this more accessibility friendly. I could have coded the span into the function, but since I often have it all dynamically generated, it worked more sustainably this way.

    In this example, I call it like this:

    the_archive_title( '<h1 class="page-title">' . $title . '</h1>' );
    

    And voila. Icons in my page title.