App Proxy - Set page title and meta description

Is it possible to set the page title and meta description through an app using the frontend app proxy?

This is for SEO purposes so I can’t just do it with JS after the page has loaded.

I found some threads saying it wasn’t possible but they were 3+ years old. I’m just wondering if anything has changed?

Thanks!

2 Likes

Hi @Andrew-W ,

A framed page cannot affect the parent page, so this isn’t possible still. You would need to use the page API (product API if it’s products, collection API if it’s a collection page, etc.) to change the SEO details.

I just realized how incorrect my response was. Whoops! Of course the APIs I mentioned won’t be helpful for you to set the SEO details, as it’s an app proxy page (/a/something, for example) rather than a Shopify object page. I believe you could do this through editing the theme using liquid. Let me look into it a bit and get back to you.

Cheers,

1 Like

Hi @Busfox ,

I acctually have a solution now! I’m not at my computer at the minute but I will detail it tomorrow for anyone that finds this thread.

Thanks,
Andrew

1 Like

So just in case anyone finds this through searching.

So in rails I created a layout template with this content:

app_proxy.html.erb

{%- layout none -%}
<%= @theme.value.html_safe %>

The first line is important because that tells Shopify to render the page without any of the normal layout.

Then in controller I load the layout/theme.liquid from the theme through the API so I can change the content of it. I do a simple find and replace on the title tag and something similar (but unfortunately not very “nice” because of the way it is in the template) with the meta description. Then I put my content in with the doing a simple find an replace on the main content liquid tag. I then make sure to send this all back to Shopify with the application/liquid header so that Shopify then renders the full page as normal. Something like this:

ShopifyAPI::Base.activate_session(ShopifyAPI::Session.new(domain: @shop.shopify_domain, token: @shop.shopify_token, api_version: '2019-04'))

shop_name = ShopifyAPI::Shop.current.name
site_name = " - #{shop_name}"
page_title.concat(site_name)
meta_desc = "</title><meta name='description' content='#{meta_desc}'>"

@theme = ShopifyAPI::Asset.find('layout/theme.liquid')

content = render_to_string "index", format: :html, layout: false

@theme.value.sub!('{{ content_for_layout }}', content)
@theme.value.sub!('{{ page_title }}', page_title)
@theme.value.sub!('</title>', meta_desc)

render layout: "app_proxy", content_type: 'application/liquid'

It’s not a perfect solution, but it does the job!

Thanks to Ole Thorup for his input on the Shopify Slack Partners Slack workspace.

But won’t this cause issue? As

@theme = ShopifyAPI::Asset.find('layout/theme.liquid')

is an API call and will slow things down and not to mention API limits (2/s and 40 leaky bucket max) and can not be scaled.

1 Like

You’re absolutely right, it’s not ideal.

Here is a better way.

In your app_proxy layout template:

<!-- assign content   -->

  <%- if @page_title -%> 
  {% capture page_title %}
    <%= @page_title %>
  {% endcapture %}
  <%- end -%>

  <%- if @meta_desc -%> 
  {% capture page_description %}
    <%= @meta_desc %>
  {% endcapture %}
  <%- end -%>

  {% capture content_for_layout %}
    <%= yield %>
  {% endcapture %}

Then in your app_proxy controller:

@page_title = "Some Page Title"
@meta_desc = "Some meta description"

render layout: "app_proxy", content_type: 'application/liquid'

Much cleaner and no API hits!

5 Likes

Is there anyway to do the same thing for facebook (ex: og:image) and twitter (ex:twitter:image) metatags?