Shopify Script to remove shipping option when products with a specific tag exists

If you want to remove a shipping option when specific products are in the cart then you can use Shopify Scripts.

For example, if dangerous goods are included that cannot be shipped using express shipping…

dangerous_goods_flag = false;
dangerous_goods_tag = 'Dangerous Goods';
shipping_rate_to_remove = 'EXPRESS';

Input.cart.line_items.each do |line_item|
  product = line_item.variant.product
  if line_item.variant.product.tags.include?(dangerous_goods_tag)
    dangerous_goods_flag = true;
  end
end

Output.shipping_rates = Input.shipping_rates.delete_if do |shipping_rate|
  if dangerous_goods_flag
    shipping_rate.name.upcase.start_with?(shipping_rate_to_remove)
  end
end

View a list of transactions in Google Analytics made when served by operator using Zopim (Zendesk Live Chat)

Sometimes you want to see the actual transactions in Google Analytics made during a session where the customer was served by a live chat operator (in this case Zopim – now called Zendesk live Chat).

To create a segment for each person called “Zopim – Served by “:

  • Create a new segment
  • Set conditions to include all sessions where Event Label =

Go to the “Conversions > Ecommerce > Transactions” report

Apply the above segment.

Set the date range (eg. last 30-days).

Google analytics transactions served by operators report

Shopify (not Plus) Google Tag Manager Checkout Page Data Layer

Intro

When using Shopify Standard (not plus) you add the Google Tag Manager snippets to your theme layout file in the head and body as per standard instructions, and then you need to add some code and setup for tracking conversions from the order page. Follow these steps:

Add this code to checkout scripts

Go to Settings > Checkout > Scripts

{% if first_time_accessed %}

<script>

var lftOrders = {{ customer.orders.size }};
var custType = 'repeatcustomer';
if (lftOrders == 1)
{
 custType = 'newcustomer';
}

var coupons = 'None';  
{% assign lcoupons = "" %} 
{% for discount in order.discounts %}  
 {% assign lcoupons = lcoupons | append:  discount.code | upcase   %}
{% endfor %}

var dataLayer = window.dataLayer = window.dataLayer || [];
dataLayer.push(
{
 'ecommerce' : {
  'purchase': {
   'actionField': {
   'id': '{{order.order_number}}',
   'revenue': {{total_price | times: 0.01}},
   'subtotal': {{subtotal_price | times: 0.01}},
   'tax': {{tax_price | times: 0.01}},
   'shipping': {{shipping_price | times: 0.01}},
   'customerType': custType,
   'lifetimeOrders': lftOrders,
   'email': '{{order.email}}',
   'coupon': '{{ lcoupons }}'
  },
  'products': [
  {% for line_item in line_items %}
   {
    'id': '{{line_item.sku}}',
    'name': '{{line_item.vendor | append: ' - '  | append: line_item.product.title}}',
    'category': '{{line_item.product.type}}',
    'brand': '{{line_item.vendor}}',
    'price': {{line_item.line_price | times: 0.01}},
    'quantity': {{line_item.quantity}}
   },
  {% endfor %}]
  }
 }
}
);
</script> 

<!-- enter the google tag manager head and body code here //-->

{% endif %} 

Define some variables in Google Tag Manager

  • Create a new constant user defined variable called gaAccountId with value = YOURGAACCOUNTID.
  • Create a new constant user defined variable called gaCrossDomains with value = “mywebsite.com,checkout.shopify.com”
  • Create a new constant user defined variable called gaDomain with value = “auto”
  • Optionally create variables based on the data layer. For example:
    • Create a Data Layer Variable for OrderID named transOrderID with value ecommerce.purchase.actionField.id
    • Create Data Layer Variables for Revenue, Shipping, Tax, Coupon, SubTotal, Email, CustomerType. eg transRevenue with value ecommerce.purchase.actionField.revenue
  • Create a page view trigger named “Transaction” with 2 conditions:
    • Page url matches RegEx(ignore case) https://checkout.shopify.com/(.*)/orders/(.*)thank(.*)
    • Referrer does not contain myshopify.com/admin/orders/

Create Google Analytics tag (type = Universal Analytics)

  • Tracking ID : {{gaAccountID}} – This is the variable we created where we stored our TrackingID
  • allowLinker: true
  • cookieDomain: {gaDomain}}
  • Enable Enhanced Ecommerce Features – Check
  • Use data layer – Check
  • Enable Display Advertising Features – Check
  • Auto Link Domains: {{gaCrossDomains}}
  • Use Hash as Delimiter: False
  • Decorate Forms: False
  • Under Triggering
    • Select All pages
    • Select Add Exception, and select Transaction.

Create Google Analytics Transaction Tag

  • Copy the tag we created above
  • Remove all the triggers and excepts
  • Select the trigger to the Transaction trigger we initially created.

References:

  • https://help.shopify.com/manual/reports-and-analytics/google-analytics/google-tag-manager
  • https://www.dbmarketer.com/db-marketer/google-tag-manager-on-shopify/
  • https://github.com/toddheslin/gtm-ecommerce-platforms/blob/master/shopify/shopify.md

Shopify FAQ page template with automatic questions and answers using jQuery

<div class="page-title clearfix">
  <div class="page-title-inner">
    <div class="page-title-title">
      <h1 class="sweetsansmedium"><span>{{ page.title }}</span></h1>
    </div>
  </div>            
</div>
<div class="page-wrapper clearfix faq">
  <div class="page-container">
    <div class="rte page-container-content">
      {{ page.content }}
    </div>
  </div>
  <div class="page-follow">
    {% include 'help-menu' %}
  </div>
</div>

<script>
 jQuery(function($) {
   
   $('.page-container-content').children(':not(h1):not(h2)').hide();
   $('.page-container-content h2').click(function() {
        $(this).toggleClass('open');
        $(this).nextUntil('h2').toggle();
     	
    });

   }); 
</script>

Shopify section for adding different header images for each page

Shopify sections are useful for creating home pages with multiple sections that you can customise and swap around. However, off-the-shelf they are limited because you can’t target content to specific collections, products, pages or blog articles.

If you want to create sections targeted to specific collections, products, pages or blog articles you need to create a reference to them in the section schema.

This example allows you to add a page image title to a specific page. You can use this method to create sections for other templates too – for example an image gallery.

This code outputs the section if the current page handle matches the setting “page_title_page”:

{% if section.blocks.size > 0 %}
  {% for block in section.blocks %}
    {% if block.settings.page_title_page == page.handle %}
        <div class="page-title-image" style="background-image:url({{block.settings.page_title_image | img_url: '2048x'}})">
            <div class="page-title-image-text">
                <h1>{{ page.title }}</h1>
                <p>{{page.metafields.global.description_tag}}</p>
            </div>
        </div>
    {% endif %}
  {% endfor %}
{% endif %}

This schema includes a field called "page_title_page" where an admin can select the page they want the image to appear:

{% schema %}
  {
    "name": "Page titles",
    "class": "page-title-sections",
    "max_blocks": 100,
    "blocks": [
      {
        "type": "page-title-section",
        "name": "Page title",
        "settings": [
          {
            "type": "page",
            "id": "page_title_page",
            "label": "Page",
            "info": "Select the page to display this title"
          },
          {
            "type": "image_picker",
            "id": "page_title_image",
            "label": "Image",
            "info": "4096px wide required"
          }
        ]
      }
    ]
  }
{% endschema %}

Mailchimp iCal Link

To get your list URL:

Click on Lists > list > Sign-up forms

Click on your sign up form url to open it in a new window

The url will be something like this:

http://<ACCOUNT_NAME>.usX.list-manage.com/subscribe?u=<USER_ID>&id=<LIST_ID>

Get those details and add the following link calendar by URL

http://<ACCOUNT_NAME>.usX.list-manage.com/ical?u=<USER_ID>&id=<LIST_ID>

Conditional click events on a Youtube Video (check state if playing or stopped)

I wanted to create on click events:

  • When the video playing send user to another page
  • When the video is stopped, re-start the video

Requried javascript API:

<script src="https://www.youtube.com/iframe_api"></script>

HTML mark-up

<div class="herovideo"> <!-- this is the wrapper //-->
  <div class="herovideo-clicker"></div> <!-- this is the clicker //-->
  <div class="video-wrapper"> <!-- this is a responsive wrapper //-->
    <div id="video-placeholder"></div> <!-- this gets replaced with iframe //-->
  </div>
</div>

CSS:

<style>
	.video-wrapper {   }
	.herovideo { position:relative;  }
	.herovideo-clicker { z-index:99; position:absolute; width: 100%; height: 100%; cursor:pointer;}
	.herovideo .video-wrapper { position:relative; z-index:9; }
</style>

Javascript that will:

  • Initialise the player and define it’s appearance
  • Do the responsive resizing
  • On stae change, set the click event
<script>

var player;
function onYouTubeIframeAPIReady() {
	player = new YT.Player('video-placeholder', {
		width: 1280,
		height: 720,
		videoId: 'Write your Youtube Video ID here',
		playerVars: {
			modestbranding: 1,
			autoplay: 1,
			controls: 0,
			enablejsapi: 1,
			fs: 0,
			rel: 0,
			showinfo: 0,
			color: 'white'
		},
		events: {
			onReady: initialize,
			onStateChange: onytplayerStateChange
		}
	});
}

function initialize(){

	var $allVideos = $("iframe[src*='//player.vimeo.com'], iframe[src*='//www.youtube.com'], object, embed"),
		$fluidEl = $(".video-wrapper");

	$allVideos.each(function() {
	  $(this)
	  .attr('data-aspectRatio', this.height / this.width)
	  .removeAttr('height')
	  .removeAttr('width');
	});

	var newWidth = $fluidEl.width();
	  $allVideos.each(function() {
		var $el = $(this);
		$el
		.width(newWidth)
		.height(newWidth * $el.attr('data-aspectRatio'));
	  });

}
  
function onytplayerStateChange(newState) {

  if(newState.data == 1) {
	 // take the user to a new page while the video is playing
	 $( ".herovideo-clicker").unbind( "click" );
	 $('.herovideo-clicker').on('click', function(){
		window.location.href = 'write your URL here'; 
		return false;
	 });
  } else  {
	// restart the video if it is not playing
	$( ".herovideo-clicker").unbind( "click" );
	$('.herovideo-clicker').on('click', function(){
		player.playVideo();
		return false;
	});
  }
}

</script>

References:

  • https://github.com/chriscoyier/Fluid-Width-Video
  • https://developers.google.com/youtube/iframe_api_reference