Local Commerce

Justin Jackson lays out the case for turning all of our favourite local stores into a viable Amazon competitor in his post Fight Amazon. It got me thinking about the problems I’ve had trying to buy things from local stores over the past year, and maybe some solutions.

Justin musing about how local stores can compete with Amazon.

Local Commerce Problems

I try to support local stores when I can. I don’t usually buy clothes, (somehow I’m still clothed), so I can’t speak knowledgeably about clothing shopping, but there have been some instances over the past year when I’ve been incredibly frustrated with local shopping.

It’s the bike shoes that the bike shop had to order twice and took a month to get, late in the season, or the bike brake levers that the bike shop ordered the model for the wrong kind of brake, or the indoor soccer shoes that, even after checking the Sport Chek website were not in stock, or when our portable washing machine broke down an there was no way to buy one locally without actually visiting or calling all the appliance stores to check their stock. Don’t even get me started on trying to buy several yards of cloth when someone in the family is making costumes for a dance recital.

In all of these cases a service that could tell me where products are in stock locally would have solved my problem. Actual purchasing and delivery would make things even better for some products.

The Inventory Problem

Where do I go to buy this?

For stores that already have E-Commerce systems in place it’s probably not too hard to answer this question. The problem is making sure that the E-Commerce systems exist, and have accurate inventory numbers. I haven’t worked in retail for a long time, and when I did we weren’t using anything computerized to record inventory. These days I think some, (but not all!), stores to have computerized inventory but making the systems used in stores talk to E-Commerce systems may be difficult.

For stores that already have reliable stock levels in their E-Commerce systems it should be relatively simple to know their inventory numbers using something like a Google Product Feed. That could be used either by other local stores who are willing to refer customers to competitors with products in stock, or by an aggregator that provides a local shopping experience.

Shipping

I should also mention shipping: It’s expensive, and it’ll be tough to compete against Amazon, but there’s probably a way to make it happen, and it’s not my area of expertise so I don’t know if any of my ideas are realistic.

The Business Problem

If the technical side works, and we have a bunch of local stores that can take orders online, ship easily and inexpensively, and find alternative sources for items they don’t have, and we have an aggregator where people can go to shop instead of Amazon, we still have a business problem, or two:

  1. Why would a store recommend that a customer go buy from their competitor now instead of trying to take the order themselves and order in the product?
    • Justin mentions commissions in his video. Why would a store pay a commission to its competitor instead of trying to get the sale itself some other way?
  2. How does the aggregator make money without becoming a pay-to-play advertising service?
    • Maybe commissions here too, but is it possible to get enough store owners on board with paying the commission instead of taking their chances with Adwords?

Next?

I doubt that I’ll be the person to try to solve these problems, but someone should.

To get to the level of a real, local-everywhere Amazon alternative let’s start with some technical questions.

Technical Questions:

  • Do stores even use computers to track stock?
    • Does that change if they sell online?
  • How hard is it to make in-store stock-tracking software talk to E-Commerce software?
    • What is even being used to track stock in stores?
    • Does it have APIs? Can it send notifications to other systems when stock levels change, or receive notifications to change its internal level when an E-Commerce order is received?
    • Do we have a good way of identifying the same product across multiple stores? I know that GTINs exist, but suspect they’re less than perfect.

If you know the answers to these, or have more questions, post in the comments like it’s 2005, or we can talk about it on Twitter.

Slashlocal: Someone is already trying

A parent I know from my kids school runs Slashlocal, which is trying to solve some of the local problems. I downloaded it today and will see if it helps me solve their problems. I’m worried their pricing model will discourage stores from putting their entire inventory online, but I believe the product is young they’re working hard to help on-board customers at no cost during the current crisis, so maybe changes are coming.

Maybe I’ll build a WooCommerce extension?

If you’re interested in a WooCommerce extension to show other places to buy an item when your store is out of stock or you don’t carry what the customer is looking for let me know. If there’s enough interest I’ll build it.

Adding Google Ads and Microsoft Advertising Conversion Tags to WooCommerce

Adding Google Ads and Microsoft Advertising conversion tracking tags to WooCommerce powered E-commerce shops can seem confusing at first: WooCommerce templates are like a huge Russian nesting doll and it’s unclear where to put the tags. On top of that Google wants their tags as close to the top of the document as possible, but many tutorials suggest using the woocommerce_thankyou hook, which dumps its output right in the middle of the body.

Use Any WordPress Hook

Luckily we can just use WordPress hooks to insert conversion tags where we need them, so long as we make sure we’re on the “Thanks for your order” page, and check that the order is a status that we want to count as a conversion. Here’s how we can do that:

/**
 * This function can be hooked onto any normal WordPress hook. Maybe wp_head,
 * or wp_footer, or even a sidebar if you really want.
 * @return [type] [description]
 */
function jb_do_stuff_on_order_complete_page() {
	// is_order_received_page() is part of WooCommerce
	// if there's a possibility that the page is loaded without WooCommerce
	// you could check to make sure it exists:
	if(!function_exists('is_order_received_page')) return;

	if(is_order_received_page()) {
		global $wp;
		$order = wc_get_order($wp->query_vars['order-received']);
		if($order && !$order->has_status( 'failed' )) {
			// Do what we need here.
		}
	}	
}

Set Up Conversion Tracking

Both Google and Microsoft have two parts to their tracking tag: a global tag that goes on every page of the website, (Microsoft calls this a UET tag, for “Universal Event Tracking“), and a conversion snippet. Both companies ask that that the global tag appears first in the document’s source. For Google this is because the gtag() function used by the conversion snippet is defined by the global tag.

Google Ads

Google really likes their global tag to be as high in the page’s source as possible – right after the opening <head> tag if possible. Because of this I often put the global tag right into header.php. A more portable solution is to use the wp_head hook so we’ll do that here:


function jb_set_up_google_tags() {

	// Start with the global tag.
?>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXX-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'UA-XXXXXXX-1');	// sets up Google Analytics - Google will give you the exact value
  gtag('config', 'AW-XXXXXXX');		// added for the conversion - Google will give you the exact value

  if (window.performance) {
    var timeSincePageLoad = Math.round(performance.now());
    gtag('event', 'timing_complete', {
      'name': 'load',
      'value': timeSincePageLoad,
      'event_category': 'JS Dependencies'
    });
  }
</script>
<?php

	// Add the conversion tag IF this is an Order Complete page.
	if(is_order_received_page()) {
		global $wp;
		$order = wc_get_order($wp->query_vars['order-received']);
		if($order && !$order->has_status( 'failed' )) {
?>		
<!-- Event snippet for Sales conversion page -->
<script>
  gtag('event', 'conversion', {
      'send_to': 'AW-XXXXXXX/XXXXXXXXX__XXXXX',		// Google will provide this value.
      'value': <?php echo $order->get_subtotal(); ?>,
      'currency': 'USD',							// Change you deal with a different currency. Or set it dynamically.
      'transaction_id': '<?php echo $order->get_order_number(); ?>'
  }); 
</script>
<?php
		}
	}
}

// Set priority 1 to appear as soon as possible in the wp_head.
add_action( 'wp_head', 'jb_set_up_google_tags', 1 );

Boom! That’s it for Google.

Microsoft Advertising

Microsoft advertising is very similar, except they seem to suggest that they want the conversion snippet before the closing </body> tag, and don’t seem to mind about the UET tag, so let’s just put them both in the wp_footer:

function jb_add_microsoft_advertising_tags() {

	// Start with the UET tag that goes on every page.
?>
<script>(function(w,d,t,r,u){var f,n,i;w[u]=w[u]||[],f=function(){var o={ti:"XXXXXXX"};o.q=w[u],w[u]=new UET(o),w[u].push("pageLoad")},n=d.createElement(t),n.src=r,n.async=1,n.onload=n.onreadystatechange=function(){var s=this.readyState;s&&s!=="loaded"&&s!=="complete"||(f(),n.onload=n.onreadystatechange=null)},i=d.getElementsByTagName(t)[0],i.parentNode.insertBefore(n,i)})(window,document,"script","//bat.bing.com/bat.js","uetq");</script>
<?php

	// Then add the conversion tag IF this is an Order Complete page.
	if(is_order_received_page()) {
		global $wp;
		$order = wc_get_order($wp->query_vars['order-received']);
		if($order && !$order->has_status( 'failed' )) {

			$order_info = [
				'revenue_value' => $order->get_subtotal(),
				'currency' => 'USD'
			];
?>
<script>
   window.uetq = window.uetq || [];
   window.uetq.push('event', '', <?php echo json_encode($order_info); ?>);  
</script>
<?php
		}
	} // end if this is an order received page.		

}
add_action( 'wp_footer', 'jb_add_microsoft_advertising_tags', 90 ); // Priority 90 to appear near the end.

Microsoft’s documentation on adding the conversion snippet is somewhat confusing. It talks about adding extra Javascript functions to supply the conversion value and doesn’t say what data type the conversion value should be, (let me know if you know). A Javascript function to extract the conversion value from the DOM might be a good idea when there’s no server-side access to the purchase data, but if you’re developing a WooCommerce theme or plugin you have the access you need to just print the conversion value in the tag with PHP, (as we did above).

Conclusion

That’s it. I heard that some people have trouble getting Bing working, (probably because of the extra-confusing directions from Microsoft), and I had trouble finding resources on adding conversion tags to the header for Google Ads. Hopefully this helps people with one, (or both), of the same questions.