All Posts By

Philip Tomlinson

eCommerce Work

Crowdfunding as a Native Advertising Channel

Another post about a talk at RDV_MARKETING from the guys from Alexandre Boucherot from ulule.com. Ulule is a crowdfunding platform that has been available to Canadians for about a year.

Types of Crowfunding

There are three types. The first is the standard type like Kickstarter, Users give you money in exchange for perks. The next offers equity. That means that users get a cut of your profits. The last is where users lend you money for your products which you will need to pay back.

Why Use Crowfunding

Crowdsourcing allows you to create or expand your current community. It isn’t because crowdsourcing expands your reach that it create a community. It is because it allows user to get a more behind the scenes look at product development.

It is also a great way to test interest in your product. If there is no interest in your product, it just won’t get funding. For example, test new products that wouldn’t be created unless there was a extremely high demand like a product developed in the lab that will only be launched if there are enough pre-orders. It’s also a great way to get feedback from early adopters fast.

Advertising Using Crowdfunding

As a brand, you can also sponsor projects that make sense. In a similar way as the previous post about influencers, it’s possible to take advantage of high engagement of a project’s investors to reach a new group of peoples.

For example, the National Bank of project has a profile of Ulule where they showcase the type of projects they like to invest in. Heineken and Nissan have also allied with Ulule to find entrepreneur-influencers.

FYI, this presentation was super crappy. Not only was the color scheme really hard to read on the PowerPoint, but it sounded much more like a sales pitch for their platform. I really hope they fire the designer who did the PowerPoint template. Who in their right mind thinks that blue writing on an orange background is aesthetically pleasing.

eCommerce Work

How to Be Better at Influencer Marketing

As part of the conference, Infopresse is promoting on of their paid training. This particular one focuses on Influencer Marketing. Hopefully, it’s good but it sounds like it will be just a long talk about how to get people (influencers) to promote your brand on Instagram.

Why Focus on Influencer Marketing Strategies

First and foremost, Quebec is behind compared to the rest of North America in adoption Influencer Marketing strategies. In other words, it’s going to trend soon. This matters a lot for agencies that want to sell it, but trending marketing strategies are not really always good for actual businesses.

A good reason to go forward with influencer marketing is that the reach of businesses on many social networks is getting smaller and smaller. I’m pretty sure everyone has heard comments from SMB owners about their crappy Facebook posts no longer reaching everyone who has liked their business.

If you have enough data about your target audience, influencer marketing can be a way to target a specific sub-section of your potential customers. If you know 50% of your female customers who like pizza follow a specific Instagrammer, it might be a good idea to reach out to him and see what partnership possibilities exist. It might even end up costing you less than standard digital advertising.

Lastly, many people will watch YouTube reviews or read independent blog posts when making purchase decisions.

Why You Should Pay Influencers

This is pretty obvious.

  • Reach
  • Knowledge of their audience’s content preferences
  • Guaranteed engagement

How to Choose Influencers

First, it’s important to remember their audience. No point in partnering with a swimsuit Instragrammer to sell your bikinis if her audience is mainly pervy males. While the trainer offered like a gajillion different criterias, they all boiled into two points.

Influencer’s Credibility & History

Is the influencer credible? Is she respected by her peers? Does it fit your branding? Did they work with your competitors? Have they shared racist posts?

You should always ask for their history and call people who have worked with them before. You should also make sure they are professional and will send you a report after the campaign.

Influencer’s Audience & Engagement

Does it match your demographics? Who listens and engages with their posts? Are they real followers and engagement? What social media do they use? Does it fit with your branding and marketing strategy?

Types of Influencers

Bloggers, Vloggers, Instagrammers and Tweeters.

How to Find Influencers

There are paid platforms to help you find them are ultra expensive, guarantee nothing and remove some of the personal relationships that need to be built between the brand’s employees and the influencer. The best way to do it is manually!

Some Extra Tips

  • Be aware of frauds who will not produce what you want but take your money or products anyways
  • Don’t neglect medium and small influencers, they sometimes influence bigger ones and tend to be more authentic
  • Authenticity is not always crucial. Blatant product placement can work
  • Develop programs with an influencer with medium and long term goals. It’s better than just doing a 1 time thing. Might also end up being cheaper!
  • Always mesure your results at a macro and micro scale on both a quantitative (sales, traffic, etc) and qualitative (branding, quality, beauty) way.
  • Use influencers to educate audience about your product, compare your services or drive sales from their audience.

Ethical Implications

Does the influencer need to disclose your brand is using him? There have been cases where celebrities have gotten in trouble for not disclosing their association with a brand. I personally do not see a problem with this because I come from a link building background and this already seems a lot cleaner.

eCommerce Work

Tips to Better Penetrate New Markets

I’m currently attending the RDV_MARKETING where Jamie Hebert, Spotify’s Head of Marketing is talking. For those who don’t listen to music, Spotify was introduced into the Canadian market in 2014 and is a music streaming service.

His talk addresses three issues with moving a service into a new market:

  • Expanding audience once early adopters have been saturated
  • Moving from content to context
  • Adapting the service for the new audience

Moving Beyond Early Adopters

The first step he believes that any brand should do before trying to bring their services to a new country is to learn from others. For example, Target failed tremendously when trying to penetrate the Canadian market. On the other hand, GoPro has been extremely successful in making their product a internationally known brand that is accessible to more than just adrenaline junkies. Another good example would be Starbucks Canada. They began by testing the Canadian palette and what type of coffee do Canadians drink. The result was the True North Blend.

Moving from Content to Context

When users began starting using Spotify, they began by looking for specific artists or music styles. However, as they get used to the service, they begin looking for music that fits the time of day and events of their day. Instead of looking for specific songs, a user might look for a playlist that can accompany their run or commute.

They strongly believe that all content should be personalized. This is why they created Spotify Running. They noticed that many users were creating playlists for running, but multiple users do not have the luxury or knowledge to curate such a playlist. That’s why they create the service to add a layer of contextual intelligence to their content.

Adapting the service for the new market

They built a dedicated team for not only marketing in Canada but also an editorial team that builds playlists for the Canadian audience and a team to deal with independent labels and ensure Canadian have accept to local independent music.

Other than building a dedicated Canadian team, Spotify is trying to make a platform where they can showcase great Canadian talent. An example of this type of initiatve is the Spotify Sessions such as their show in Montreal with Coeur de Pirate. A weird fact is that only in Canada is that in our country these shows are not in Spotify offices! In fact, they also partner with local artists to showcase brands and help them get air play by showing the data to radio stations.

Contextuality also plays a part in adapting the service. Using a data-driven approach, they use DIB system (Data, Insights, Beliefs) when planning all marketing campaigns. They looked at the most played songs along a Toronto bus route area. Afterwards, they create a playlist for the specific bus route and looked to see the results. I’m guessing they were good as they repeated the same campaign across multiple other Canadian cities.

Lastly, Spotify creates local partnerships with many Canadian branches of big businesses. This helps increase the reach and engagement in the market. Spotify partners with local radio stations to extend radio shows into Spotify playlists.

Diary

Why I launched t.omlinson.com

I’ve finally finished the first version of t.omlinson.com.

I was getting tired of the “philtomm” as a username and domain name. It violated one of the most important rules in almost all disciplines: if you’re creating something that other people will use, make it idiot proof.

My email is philip@philtomm, with two “M”s, dot com.

The number of confused looks and the amount of people who would ignore the two “M”s warning or end up putting three “M”s was higher than expected.

In addition, the double “M” started to look just plain ugly.

I’m launching this site as is, but I will definitely work on the design in the future. I just want to get back into a more consistent blogging habit before investing me time in coding and design for this personal project.

Broken Link Warning

You may still get broken links as I didn’t do a massive clean up yet. I did try to limit the number of broken images. In any case, have fun clicking on things that lead to nowhere.

PHP WordPress

How to Customize WordPress Sidebars

If you haven’t noticed! I’ve not only migrated my domain to t.omlinson.com, but I’ve also created a child theme based off of the Redwood WordPress theme. One particular element I needed to add was different WordPress sidebars based on the category page.

Old Way of Customizing Your Sidebars

In the past, I used to buy HTML themes and convert them into WordPress themes. This avoided some of the bloat found within premium themes and required a much smaller investment. During that era, this is how I would ensure different pages could support different sidebars.

I would create a PHP file called “wordpress-sidebar.php.” Inside, I’d insert the customization that I wanted. I’d usually not use widgets because it wasn’t something I was comfortable with at the time. Afterwards, I’d just add an if statement to call on the file I just created wherever I needed to.

The code would look something like this.

<?php 
 
//if you wanted a custom sidebar for your wordpress category archive page
//you could use in_category() if you wanted to target a post within a category
 
if(is_category("wordpress"){ 
 
      //actually not sure if TEMPLATEPATH is necessary, leave a comment if you know!
 
      include(TEMPLATEPATH . '/wordpress-sidebar.php');
 
      // the else would call the default sidebar, you could use elseif to create a chain if you wanted
 
} else {
 
      // this is a command to get the default sidebar in WordPress
      // it is identical to using include 
 
      get_sidebar();
}
?>

Pretty simple, but it’s the old and wrong way to do it.

New & Better Way to Create Different WordPress Sidebars

You begin by entering into your theme or child theme’s “functions.php” file. You’ll want to add code similar to this one:

<?php 
 
// Basic was of registering new WordPress sidebars
 
if ( function_exists ('register_sidebar')) { 
    register_sidebar ('wordpress_sidebar'); 
 
    // More advanced way of adding an alternative sidebar allow you to control some of the style and CSS
    // elements. You could also use a function called register_sidebars()
    //  to create multiple WordPress sidebars but the function is not recommended. 
 
    register_sidebar( array(
        'name' => __( 'Work Sidebar', $theme_slug), //name that appears in your widget area
        'id' => 'work', //id to call your sidebar this is only variable you must specify
        'description' => __( 'Widgets in this area will be shown on all posts and pages.',  $theme_slug ),
        'before_widget' => '<li id="%1$s" class="widget %2$s">',
	'after_widget'  => '</li>',
	'before_title'  => '<h2 class="widgettitle">',
	'after_title'   => '</h2>',
    ) );
 
// Be sure to replace $theme_slug with your theme's slug! 
 
} 
?>

This will allow you to modify your sidebar using the regular widget section. Next step if similar to the previous way of adding WordPress sidebars, create a file based on the id of your newly registered sidebar. In this case, the file would be named “sidebar-work.php”.

You’ll make whatever modifications you need in that new file and make sure that your dynamic_sidebar(); function refers to your new sidebar by name. If you don’t make changes to that function, your widgets will not show up.

Now, whenever you use the get_sidebar(); function, you can call the work sidebar by doing get_sidebar(‘work’);.

If you need additional help, you should definitely do one of these three things:

  1. Read the WordPress Codex page about customizing your sidebar.
  2. Search the WordPress Development Stack Exchange.
  3. Comment below and I’ll do my best to help you out.
PHP WordPress

Modifying the WordPress Template Hierarchy to Handle Parent Categories

This is essentially plagiarism of a great post by Drew Jaynes. It took me a while to discover his post when trying to figure out how to modify the WordPress template hierarchy so I decided to share it again. Hopefully one of these pages will start to rank better.

Here’s his code with a tiny amount of additional comments:

 
//this code should be pasted into your function.php file
 
function new_subcategory_hierarchy() {  
 
    $category = get_queried_object();
 
    $parent_id = $category->category_parent;
 
    $templates = array();
 
    // preserves the classic WordPress template hierarchy for parent categories
    // or else it create a new path for sub-categories
    if ( $parent_id == 0 ) {
        // Use default values from get_category_template()
        $templates[] = "category-{$category->slug}.php";
        $templates[] = "category-{$category->term_id}.php";
        $templates[] = 'category.php';      
    } else {
        // Create replacement $templates array 
        $parent = get_category( $parent_id );
 
        // Current first
        $templates[] = "category-{$category->slug}.php";
        $templates[] = "category-{$category->term_id}.php";
 
        // Parent second
        $templates[] = "category-{$parent->slug}.php";
        $templates[] = "category-{$parent->term_id}.php";
        $templates[] = 'category.php';  
    }
    return locate_template( $templates );
}
 
add_filter( 'category_template', 'new_subcategory_hierarchy' );

Personally, I find the WordPress Template Hierarchy pretty good. Other than it’s issue with dealing with sub-categories, I’ve never really had a problem with its flow. In fact, I could have easily just copy pasted a template file for each sub-category based on its parent.

Diary WordPress

Merged All My Old Web Properties

I could go on a rant about how I want to create a stronger personal brand, but that would be bullshit.

While doing some spring autumn cleaning, I discovered a few funky files informing me that I’ve been hacked.

I had neglected to update core WordPress, themes and plugins of a lot of my first web projects. I have payed the price for my laziness.

I feel like it will be easier to manage and less risky if I just begin to dump it all my content here.

I had not found a niche that I was particular passionate about. I also hadn’t/haven’t found the willpower to force myself into becoming obsessed about a topic. So I am not too affected by the hack (most of the sites had been abandoned), it’s just pretty annoying to have to half-ass redirect everything late at night.

In any case, there’s a bunch more cleaning to be done in the next few days.

AdWords JavaScript

AdWords Broken URL Checker That Won’t Timeout Ever

A common problem with broken URL checker scripts is that they tend to timeout when running on large AdWords accounts. This is because Google would rather you use their API.

I’d love to start using the Google API and I even got my test MCC account up and running. The problem is that I’m not really at that level of coding comfort yet, so I’ve started playing with scripts. The following Broken URL Checker was my first time using JavaScript!

Don’t get me wrong, there’s a few great link checker AdWords scripts out there and some not so great ones.

Here’s one script that works perfectly fine on smaller AdWords account.

Google also has it’s own Link Checker script that checks 800 URLs every execution. It’s actually pretty neat but I haven’t tested it out.

In theory, Google’s Link Checker should also work if the Free AdWords Scripts keeps timing out. I decided to just write my own little version of his script that allows me to segment my account. In other words, instead of running 1 script to check all my destination pages for errors, I run multiple scripts that check a unique set of campaigns each.

It’s heavily inspired (partially stolen) from Russel Savage’s script but there are some key differences.

The most notable difference is the fact that I no longer take a look at keyword destination URLs. I don’t have that many in my account so I have a separate script that doesn’t use my custom campaign filter.

In fact, the filter in the AdGroup selector is the only other difference other than some comments that I just added.

My Broken URL Checker Code

 
/****************************
* Broken URL Checker /w Segments
* Version 1.0
* Created by: Philip Tomlinson (@philtomm)
* t.omlinson.com
* Modified Version of Russ Savage's Broken URL Finder
* FreeAdWordsScripts.com
****************************/
 
function main() {
  // You can add more if you want: http://goo.gl/VhIX
  var BAD_CODES = [404,500];
  var TO = [''/* insert email in the quotes like this 'email_address@example.com'*/];
  var SUBJECT = 'Broken AdWords for Campaign URL Report - ' + _getDateString(); 
  //You may want to add what letters you're targeting
  var HTTP_OPTIONS = {
    muteHttpExceptions:true
  };
 
  // This is the start of my changes
  // Establishing variables for the alphabet filter
  var alphaIndex;
  var alphabet = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
  var iters = [];
 
  // This filter selects all campaigns starting with the letters A to G.
  for (alphaIndex = 0 /*starting letter number*/; alphaIndex < 7 /*number - 1 equals last letter */; ++alphaIndex){  
 
  var iterPush = [
    AdWordsApp.ads()
      .withCondition("Status = 'ENABLED'")
      .withCondition("AdGroupStatus = 'ENABLED'")
      .withCondition("CampaignStatus = 'ENABLED'")
      .withCondition("Type = 'TEXT_AD'")
      .withCondition("CampaignName STARTS_WITH '" + alphabet[alphaIndex] + "'")
      .get(),
];
 
    var iters = iters.concat(iterPush);
 
    };
 
  /* Everything else is from Russel Savage's post here: http://www.freeadwordsscripts.com/2013/04/report-on-broken-urls-in-your-account.html */
 
  var already_checked = {}; 
  var bad_entities = [];
  for(var x in iters) {
    var iter = iters[x];
    while(iter.hasNext()) {
      var entity = iter.next();
      if(entity.getDestinationUrl() == null) { continue; }
      var url = entity.getDestinationUrl();
      if(url.indexOf('{') >= 0) {
        //Let's remove the value track parameters
        url = url.replace(/{[0-9a-zA-Z]+}/g,'');
      }
      if(already_checked[url]) { continue; }
      var response_code;
      try {
        Logger.log("Testing url: "+url);
        response_code = UrlFetchApp.fetch(url, HTTP_OPTIONS).getResponseCode();
      } catch(e) {
        //Something is wrong here, we should know about it.
        bad_entities.push({e : entity, code : -1});
      }
      if(BAD_CODES.indexOf(response_code) >= 0) {
        //This entity has an issue.  Save it for later. 
        bad_entities.push({e : entity, code : response_code});
      }
      already_checked[url] = true;
    }
  }
  var column_names = ['Type','CampaignName','AdGroupName','Id','Headline/KeywordText','ResponseCode','DestUrl'];
  var attachment = column_names.join(",")+"n";
  for(var i in bad_entities) {
    attachment += _formatResults(bad_entities[i],",");
  }
  if(bad_entities.length > 0) {
    var options = { attachments: [Utilities.newBlob(attachment, 'text/csv', 'bad_urls_'+_getDateString()+'.csv')] };
    var email_body = "There are " + bad_entities.length + " urls that are broken. See attachment for details.";
 
    for(var i in TO) {
      MailApp.sendEmail(TO[i], SUBJECT, email_body, options);
    }
  }  
}
 
//Formats a row of results separated by SEP
function _formatResults(entity,SEP) {
  var e = entity.e;
  if(typeof(e['getHeadline']) != "undefined") {
    //this is an ad entity
    return ["Ad",
            e.getCampaign().getName(),
            e.getAdGroup().getName(),
            e.getId(),
            e.getHeadline(),
            entity.code,
            e.getDestinationUrl()
           ].join(SEP)+"n";
  } else {
    // and this is a keyword
    return ["Keyword",
            e.getCampaign().getName(),
            e.getAdGroup().getName(),
            e.getId(),
            e.getText(),
            entity.code,
            e.getDestinationUrl()
           ].join(SEP)+"n";
  }
}
 
//Helper function to format todays date
function _getDateString() {
  return Utilities.formatDate((new Date()), AdWordsApp.currentAccount().getTimeZone(), "yyyy-MM-dd");

N.B. I did not test my code after adding some comments. If this doesn’t work, please tell me in the comments! I’m a known typo machine.

SEO

Steal backlinks from a competitor’s product pages

Last month, a guest post by Chris Laursen caught my eye. It was about link building tactics for eCommerce that do not require quality content. One prospecting tactics Cris used was uncovering backlink profiles of closed businesses. I’ve decided to test something slightly different. Rather than look at closed businesses, the goal will be to steal backlinks from an active competitor.

In theory, webmasters should want to refer their readers to a place where they can actually buy the mentioned product right? That’s why I decided to uncover how many broken links to products page and links to products that are out of stock I can find for one company. If the results are satisfactory, I might test out outreach with a real competitor of mine.

I decided to run my prospecting test with SSENSE. Why them? I have a friend that works there and I don’t want to warn my competitors that I’m planning to steal backlinks from them.

Getting Those Dirty Leads

I was pleasantly surprised to see that SSENSE has a great URL structure. By specifying that the page is a product page in the URL, I’ll be able use search for backlinks using the prefix in Ahref.

ssence-url-structure

Of course, it also means I’ll only be checking the Men’s section. By checking only one backlink per domain, I’ve gotten 1510 results. Not bad!

If You Don’t Got That Prefix

If SSENSE had a flat URL structure (http://www.domain.com/product-name), I would have needed to figure out a unique footprint associated to the product pages, scape the Link URLs for it, remove the fat and continue to the next step.

Find Those 404 Errors

I’m going to assume that my fake eCommerce store carries an identical inventory to SSENSE. If that wasn’t case, I might be interested in cutting out various brands or item categories.

Some people might be tempted to this:

http-status-check-wrong

Doing a such a check with SeoTools for Excel isn’t 100% wrong. It would just be a waste of time because there are definitely duplicate URLs in that Ahref export. In this case, I was able to reduce the list by 1/3 by copying the Link URLs to another sheet and removing duplicates. Not to shabby.

If you got some free tools that do reliable HTTP status checks really fast, I’d love hear about them in the comments because it’s annoying to wait for this check to end.

Once that’s done, copy and overwrite the column by pasting the results as values rather than formulas. This is a habit I have developed when dealing with large columns of function and it can really save you headaches.

ssence-http-results

For some weird reason, SSENSE redirects users to their 404 page. These redirections only account for less than 10% of all 301 redirects. The other redirects were due to a change in the URL structure. They were not redirecting sold out products to their home page or related pages.

Using VLOOKUP, I was able to confirm that there was only one domain per 404 error. In any case, that’s still 9 potential links to steal if you’re carrying the product or something extremely similar!

Discover What’s Out of Stock

While I was waiting for the HTTP status check to finish, I confirmed that sold out products pages aren’t redirected and are easily identifiable.

ssence-sold-out

Because SSENCE has implemented rich snippets for products, it’s really easy to scrape their product availability using xPath.

If you’re using SeoTools for Excel, don’t be tricked into using =XPathOnUrl(H2,"//meta[@itemprop='availability']/@content"). That function will not give you the content of the meta tag, it will only confirm that it exists. You must use =XPathOnUrl(H3,"//meta[@itemprop='availability']","content") instead to see the actual contents.

Once again, there’s a bit of wait.

ssence-out-of-stock

Out of all the valid URLs, over 75% were out of stock! If I were SSENSE, I’d be checking to see how much referral traffic the product pages are getting…

However, that’s good news for the people who still have those products in stock and want to steal those links.

Alternative Method

If product rich snippets aren’t implemented, you could always use ScrapeBox to check if “Sold Out” is present on the page.

What’s Left To Do

Before even beginning to harvest emails, you’ll just need make sure you have the item in stock.

The only roadblock I can see is that some of these backlinks are in articles about SSENSE. Therefore, it may be hard to pitch a replacement link. However, if you have the product in stock and a good price, you may still be able to get a link on the same page if the webmaster is open to it.

I’m still amazed that over 1000 external links were to out of stock products.

If you’ve tried this method, I’d love to hear what your results where.

SEO

Google+ profile links show up as nofollow when logged in

The second link building tactic from Backlinko’s blog post also ended up being a bit trickier than expected. This time it wasn’t because of a WordPress RSS feed issue, it’s because Google+ shows all profile links as nofollow when you’re logged in.

What is even more misleading is that selecting to view your public profile also shows a nofollow link.

google-plus-profile-link

I decided to double check some other Google+ profiles. All of them actually had dofollow links in their story section. I logged out and checked my true public profile and the link became follow!

dofollow google plus profile link

I have no idea why Google+ changes the follow attribute of profile links this way. Maybe Google is trying to limit SEO abuse?