Publicaciones de Instagram

En este tutorial vamos a agregar el componente para mostrar en la página de inicio las últimas publicaciones de una cuenta de instagram.

HTML

Lo primero que vamos a hacer es crear la carpeta home dentro de la carpeta snipplets

1. Dentro de la carpeta creada, agregamos un snipplet con el nombre home-instafeed.tpl con el siguiente contenido:

{% if settings.show_instafeed  %}
    <section class="section-instafeed-home">
        <div class="container">
            <div class="row">
                {% set instuser = store.instagram|split('/')|last %}
                <div class="col-12 text-center">
                    {% if store.instagram %}
                        <a target="_blank" href="{{ store.instagram }}" class="instafeed-title">
                            {% include "snipplets/svg/instagram.tpl" with {svg_custom_class: "icon-inline icon-2x svg-icon-text"} %}
                            <h3 class="instafeed-user">{{ instuser }}</h3>
                        </a>
                    {% else %}
                        <div class="instafeed-title">
                            {% include "snipplets/svg/instagram.tpl" with {svg_custom_class: "icon-inline icon-2x svg-icon-text"} %}
                            <h3 class="instafeed-user">{{ "Instagram" | translate }}</h3>
                        </div>
                    {% endif %}
                </div>
            </div>
        </div>
        <div id="instafeed" class="row no-gutters">  
        </div>
    </section>
{% endif %}

2. Cómo queremos mostrar las últimas publicaciones de instagram en la página inicial, agregamos el llamado a home-instafeed.tpl dentro del template templates/home.tpl. 

Vale la pena mencionar que es una funcionalidad opcional, por lo que va a depender de si está activada o no desde la sección de Personalizar tu diseño actual en el Administrador nube. 

{% include 'snipplets/home/home-instafeed.tpl' %}

3.  Por último para la parte de HTML, necesitamos agregar una carpeta SVG dentro de la carpeta snipplets. Acá vamos sumar los SVGs que usamos para los iconos.

instagram.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"/></svg>

heart.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M458.4 64.3C400.6 15.7 311.3 23 256 79.3 200.7 23 111.4 15.6 53.6 64.3-21.6 127.6-10.6 230.8 43 285.5l175.4 178.7c10 10.2 23.4 15.9 37.6 15.9 14.3 0 27.6-5.6 37.6-15.8L469 285.6c53.5-54.7 64.7-157.9-10.6-221.3zm-23.6 187.5L259.4 430.5c-2.4 2.4-4.4 2.4-6.8 0L77.2 251.8c-36.5-37.2-43.9-107.6 7.3-150.7 38.9-32.7 98.9-27.8 136.5 10.5l35 35.7 35-35.7c37.8-38.5 97.8-43.2 136.5-10.6 51.1 43.1 43.5 113.9 7.3 150.8z"/></svg>

comments.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M532 386.2c27.5-27.1 44-61.1 44-98.2 0-80-76.5-146.1-176.2-157.9C368.3 72.5 294.3 32 208 32 93.1 32 0 103.6 0 192c0 37 16.5 71 44 98.2-15.3 30.7-37.3 54.5-37.7 54.9-6.3 6.7-8.1 16.5-4.4 25 3.6 8.5 12 14 21.2 14 53.5 0 96.7-20.2 125.2-38.8 9.2 2.1 18.7 3.7 28.4 4.9C208.1 407.6 281.8 448 368 448c20.8 0 40.8-2.4 59.8-6.8C456.3 459.7 499.4 480 553 480c9.2 0 17.5-5.5 21.2-14 3.6-8.5 1.9-18.3-4.4-25-.4-.3-22.5-24.1-37.8-54.8zm-392.8-92.3L122.1 305c-14.1 9.1-28.5 16.3-43.1 21.4 2.7-4.7 5.4-9.7 8-14.8l15.5-31.1L77.7 256C64.2 242.6 48 220.7 48 192c0-60.7 73.3-112 160-112s160 51.3 160 112-73.3 112-160 112c-16.5 0-33-1.9-49-5.6l-19.8-4.5zM498.3 352l-24.7 24.4 15.5 31.1c2.6 5.1 5.3 10.1 8 14.8-14.6-5.1-29-12.3-43.1-21.4l-17.1-11.1-19.9 4.6c-16 3.7-32.5 5.6-49 5.6-54 0-102.2-20.1-131.3-49.7C338 339.5 416 272.9 416 192c0-3.4-.4-6.7-.7-10C479.7 196.5 528 238.8 528 288c0 28.7-16.2 50.6-29.7 64z"/></svg>

CSS

Requisito:

Tener agregados en tu diseño las clases helpers. Podés seguir este este pequeño tutorial para hacerlo (simplemente es copiar y pegar algunas clases, no toma más de 1 minuto).

1. Agregamos el siguiente SASS de colores en style-colors.scss.tpl (o la hoja de tu diseño que tenga los colores y tipografías de la tienda). Recordá que las variables de colores y tipografías pueden variar respecto a tu diseño:

{# /* // Margin and padding */ #}

%element-margin {
  margin-bottom: 20px;
}

{# /* // Instafeed */ #}

.section-instafeed-home {
  @extend %element-margin;
}

.instafeed-title {
  display: block;
  @extend %element-margin;
  color: $main-foreground;
}

.instafeed-info {
  color: $main-background;
  fill: $main-background;
  background: rgba($main-foreground, .6);
}

2. Agregar los estilos dentro del archivo static/style-async.tpl 

Si en tu diseño usas una hoja de estilos para CSS asíncrono, vamos a necesitar el siguiente código dentro de la misma, pero si no es el caso entonces podés unificar el CSS de los pasos 1 y 2 en un solo archivo.

{# /* // Mixins */ #}

{# This mixin adds browser prefixes to a CSS property #}

@mixin prefix($property, $value, $prefixes: ()) {
  @each $prefix in $prefixes {
    #{'-' + $prefix + '-' + $property}: $value;
  }
  #{$property}: $value;
}

{# /* // Instafeed */ #}

.instafeed-user {
    display: inline-block;
    margin: 0 0 0 5px;
  line-height: 24px;
  vertical-align: top;
}

.instafeed-link {
  display: block;
  overflow: hidden;
}

.instafeed-img {
  overflow: hidden;
  position: relative;
  padding-top: 100%;
  background-position: center center;
  background-size: cover;
  @include prefix(transition, all 0.8s ease, webkit ms moz o);
  .instafeed-info {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    padding: 0;
    text-align: center;
    opacity: 0;
    @include prefix(transition, all 0.8s ease, webkit ms moz o);
    .instafeed-info-item {
      display: inline-block;
      margin-top: 45%;
    }
  }
  &:hover,
  &:focus {
    @include prefix(transform, scale(1.03), webkit ms moz o);
    .instafeed-info {
      opacity: 1;
    }
  }
}

JS

1. Necesitamos aplicar las funciones en el archivo store.js.tpl (o donde tengas tus funciones de JS). El código que necesitamos es el siguiente:

{% if settings.show_instafeed and (template == 'home') %}

        {# /* // Instagram feed */ #}

        {% if settings.show_instafeed %}
            var width = window.innerWidth;
            if (width > 767) {  
                var resolution = "standard_resolution";
            } else {
                var resolution = "low_resolution";
            }
            var feedqty =  {{ settings.instafeed_qty }};
            {% set userid = settings.instafeed_accesstoken|split('.')|first %}

            {% set instlink = '{{link}}' %}
            {% set instimg = '{{image}}' %}
            {% set instlike = '{{likes}}' %}
            var userFeed = new Instafeed({
            get: 'user',
                userId: '{{ userid }}',
                accessToken: '{{ settings.instafeed_accesstoken }}',
                resolution: resolution,
                template: '<div class="col-4"><a class="instafeed-link" href="{{instlink}}" target="_blank"><div class="instafeed-img lazyload" data-bg="{{instimg}}">{% if settings.instafeed_like %}<div class="instafeed-info"><span class="instafeed-info-item">{% include "snipplets/svg/heart.tpl" with {svg_custom_class: "icon-inline"} %} {{instlike}}</span></div>{% endif %}</div></a></div>',
                limit: feedqty
           });
           userFeed.run();
       {% endif %}
{% endif %}

2. Ahora vamos a necesitar agregar el plugin en el archivo external-no-dependencies.js.tpl o el archivo donde tengas los plugins de tu diseño. 

{% if settings.show_instafeed and (template == 'home') %}

{# /* Instafeed */ #}
(function(){var e;e=function(){function e(e,t){var n,r;this.options={target:"instafeed",get:"popular",resolution:"thumbnail",sortBy:"none",links:!0,mock:!1,useHttp:!1};if(typeof e=="object")for(n in e)r=e[n],this.options[n]=r;this.context=t!=null?t:this,this.unique=this._genKey()}return e.prototype.hasNext=function(){return typeof this.context.nextUrl=="string"&&this.context.nextUrl.length>0},e.prototype.next=function(){return this.hasNext()?this.run(this.context.nextUrl):!1},e.prototype.run=function(t){var n,r,i;if(typeof this.options.clientId!="string"&&typeof this.options.accessToken!="string")throw new Error("Missing clientId or accessToken.");if(typeof this.options.accessToken!="string"&&typeof this.options.clientId!="string")throw new Error("Missing clientId or accessToken.");return this.options.before!=null&&typeof this.options.before=="function"&&this.options.before.call(this),typeof document!="undefined"&&document!==null&&(i=document.createElement("script"),i.id="instafeed-fetcher",i.src=t||this._buildUrl(),n=document.getElementsByTagName("head"),n[0].appendChild(i),r="instafeedCache"+this.unique,window[r]=new e(this.options,this),window[r].unique=this.unique),!0},e.prototype.parse=function(e){var t,n,r,i,s,o,u,a,f,l,c,h,p,d,v,m,g,y,b,w,E,S,x,T,N,C,k,L,A,O,M,_,D;if(typeof e!="object"){if(this.options.error!=null&&typeof this.options.error=="function")return this.options.error.call(this,"Invalid JSON data"),!1;throw new Error("Invalid JSON response")}if(e.meta.code!==200){if(this.options.error!=null&&typeof this.options.error=="function")return this.options.error.call(this,e.meta.error_message),!1;throw new Error("Error from Instagram: "+e.meta.error_message)}if(e.data.length===0){if(this.options.error!=null&&typeof this.options.error=="function")return this.options.error.call(this,"No images were returned from Instagram"),!1;throw new Error("No images were returned from Instagram")}this.options.success!=null&&typeof this.options.success=="function"&&this.options.success.call(this,e),this.context.nextUrl="",e.pagination!=null&&(this.context.nextUrl=e.pagination.next_url);if(this.options.sortBy!=="none"){this.options.sortBy==="random"?M=["","random"]:M=this.options.sortBy.split("-"),O=M[0]==="least"?!0:!1;switch(M[1]){case"random":e.data.sort(function(){return.5-Math.random()});break;case"recent":e.data=this._sortBy(e.data,"created_time",O);break;case"liked":e.data=this._sortBy(e.data,"likes.count",O);break;case"commented":e.data=this._sortBy(e.data,"comments.count",O);break;default:throw new Error("Invalid option for sortBy: '"+this.options.sortBy+"'.")}}if(typeof document!="undefined"&&document!==null&&this.options.mock===!1){m=e.data,A=parseInt(this.options.limit,10),this.options.limit!=null&&m.length>A&&(m=m.slice(0,A)),u=document.createDocumentFragment(),this.options.filter!=null&&typeof this.options.filter=="function"&&(m=this._filter(m,this.options.filter));if(this.options.template!=null&&typeof this.options.template=="string"){f="",d="",w="",D=document.createElement("div");for(c=0,N=m.length;c<N;c++){h=m[c],p=h.images[this.options.resolution];if(typeof p!="object")throw o="No image found for resolution: "+this.options.resolution+".",new Error(o);E=p.width,y=p.height,b="square",E>y&&(b="landscape"),E<y&&(b="portrait"),v=p.url,l=window.location.protocol.indexOf("http")>=0,l&&!this.options.useHttp&&(v=v.replace(/https?:\/\//,"//")),d=this._makeTemplate(this.options.template,{model:h,id:h.id,link:h.link,type:h.type,image:v,width:E,height:y,orientation:b,caption:this._getObjectProperty(h,"caption.text"),likes:h.likes.count,comments:h.comments.count,location:this._getObjectProperty(h,"location.name")}),f+=d}D.innerHTML=f,i=[],r=0,n=D.childNodes.length;while(r<n)i.push(D.childNodes[r]),r+=1;for(x=0,C=i.length;x<C;x++)L=i[x],u.appendChild(L)}else for(T=0,k=m.length;T<k;T++){h=m[T],g=document.createElement("img"),p=h.images[this.options.resolution];if(typeof p!="object")throw o="No image found for resolution: "+this.options.resolution+".",new Error(o);v=p.url,l=window.location.protocol.indexOf("http")>=0,l&&!this.options.useHttp&&(v=v.replace(/https?:\/\//,"//")),g.src=v,this.options.links===!0?(t=document.createElement("a"),t.href=h.link,t.appendChild(g),u.appendChild(t)):u.appendChild(g)}_=this.options.target,typeof _=="string"&&(_=document.getElementById(_));if(_==null)throw o='No element with id="'+this.options.target+'" on page.',new Error(o);_.appendChild(u),a=document.getElementsByTagName("head")[0],a.removeChild(document.getElementById("instafeed-fetcher")),S="instafeedCache"+this.unique,window[S]=void 0;try{delete window[S]}catch(P){s=P}}return this.options.after!=null&&typeof this.options.after=="function"&&this.options.after.call(this),!0},e.prototype._buildUrl=function(){var e,t,n;e="https://api.instagram.com/v1";switch(this.options.get){case"popular":t="media/popular";break;case"tagged":if(!this.options.tagName)throw new Error("No tag name specified. Use the 'tagName' option.");t="tags/"+this.options.tagName+"/media/recent";break;case"location":if(!this.options.locationId)throw new Error("No location specified. Use the 'locationId' option.");t="locations/"+this.options.locationId+"/media/recent";break;case"user":if(!this.options.userId)throw new Error("No user specified. Use the 'userId' option.");t="users/"+this.options.userId+"/media/recent";break;default:throw new Error("Invalid option for get: '"+this.options.get+"'.")}return n=e+"/"+t,this.options.accessToken!=null?n+="?access_token="+this.options.accessToken:n+="?client_id="+this.options.clientId,this.options.limit!=null&&(n+="&count="+this.options.limit),n+="&callback=instafeedCache"+this.unique+".parse",n},e.prototype._genKey=function(){var e;return e=function(){return((1+Math.random())*65536|0).toString(16).substring(1)},""+e()+e()+e()+e()},e.prototype._makeTemplate=function(e,t){var n,r,i,s,o;{% raw %}r=/(?:\{{2})([\w\[\]\.]+)(?:\}{2})/,{% endraw %} n=e;while(r.test(n))s=n.match(r)[1],o=(i=this._getObjectProperty(t,s))!=null?i:"",n=n.replace(r,function(){return""+o});return n},e.prototype._getObjectProperty=function(e,t){var n,r;t=t.replace(/\[(\w+)\]/g,".$1"),r=t.split(".");while(r.length){n=r.shift();if(!(e!=null&&n in e))return null;e=e[n]}return e},e.prototype._sortBy=function(e,t,n){var r;return r=function(e,r){var i,s;return i=this._getObjectProperty(e,t),s=this._getObjectProperty(r,t),n?i>s?1:-1:i<s?1:-1},e.sort(r.bind(this)),e},e.prototype._filter=function(e,t){var n,r,i,s,o;n=[],r=function(e){if(t(e))return n.push(e)};for(i=0,o=e.length;i<o;i++)s=e[i],r(s);return n},e}(),function(e,t){return typeof define=="function"&&define.amd?define([],t):typeof module=="object"&&module.exports?module.exports=t():e.Instafeed=t()}(this,function(){return e})}).call(this);

{% endif %}

3. Como en este tutorial usamos la técnica de lazy load con el plugin Lazysizes, necesitamos agregarlo. Para ver como hacerlo podés leer este corto artículo y luego continuar con este tutorial.

Configuraciones

En el archivo config/settings.txt vamos a agregar el checkbox para poder activar o desactivar el componente, así como los campos para colocar el Access Token de Instagram, cantidad de publicaciones y si queremos hacer visibles la cantidad de “Me gusta” de cada publicación.

title
        title = Publicaciones de Instagram
    description
        description = El Feed de Instagram muestra automáticamente tus últimas publicaciones en la página de inicio de tu tienda
    subtitle
        subtitle = Configurar cuenta de Instagram
    i18n_input
        name = instafeed_accesstoken
        description = Access Token (Necesario para validar tu cuenta)
    subtitle
        subtitle = <a target='_blank' href='https://ayuda.tiendanube.com/como-mostrar-mis-publicaciones-de-instagram-en-mi-tienda-nube'>¿Cómo obtener el Access Token?</a>
    checkbox
        name = show_instafeed
        description = Mostrar tus publicaciones de Instagram en la página de inicio de tu tienda
    subtitle
               subtitle = ¿Cuántas publicaciones querés mostrar?
    dropdown
                name = instafeed_qty
                values
                    3 = 3 publicaciones
                              6 = 6 publicaciones
                    9 = 9 publicaciones
    checkbox
        name = instafeed_like
        description = Mostrar la cantidad de <em>‘Me gusta’</em> de cada publicación

Traducciones

En este paso agregamos los textos para las traducciones en el archivo config/translations.txt

es "Publicaciones de Instagram"
pt "Postagens do Instagram"
es_mx "Publicaciones de Instagram"

es "El Feed de Instagram muestra automáticamente tus últimas publicaciones en la página de inicio de tu tienda"
pt "O feed do Instagram exibe automaticamente suas últimas postagens na página inicial da sua loja."
es_mx "El Feed de Instagram muestra tus últimas publicaciones en la página de inicio."

es "Mostrar tus publicaciones de Instagram en la página de inicio de tu tienda"
pt "Exibir suas postagens do Instagram na página inicial da sua loja."
es_mx "Mostrar tus publicaciones de Instagram en la página de inicio de tu tienda online"

es "Configurar cuenta de Instagram"
pt "Configurar conta do Instagram"
es_mx "Configurar tu cuenta de Instagram"

es "<a target='_blank' href='https://ayuda.tiendanube.com/como-mostrar-mis-publicaciones-de-instagram-en-mi-tienda-nube'>¿Cómo obtener el Access Token?</a>"
pt "<a target='_blank' href='https://atendimento.nuvemshop.com.br/como-adicionar-o-feed-do-instagram'>Como obter o Access Token?</a>"
es_mx "<a target='_blank' href='https://ayuda.tiendanube.com/como-mostrar-mis-publicaciones-de-instagram-en-mi-tienda-nube'>¿Cómo obtener el Access Token?</a>"

es "Access Token (Necesario para validar tu cuenta)"
pt "Access Token (Necessário para validar sua conta)"
es_mx "Access Token (Necesario para validar tu cuenta)"

es "Imágenes en las publicaciones de Instagram"
pt "Imagens em posts do Instagram"
es_mx "Imágenes en las publicaciones de Instagram"

es "Imágenes en las publicaciones de Instagram"
pt "Imagens em posts do Instagram"
es_mx "Imágenes en las publicaciones de Instagram"

es "¿Cuántas publicaciones querés mostrar?"
pt "Quantos posts você deseja exibir?"
en "How many posts do you want to show?"
es_mx "¿Cuántas publicaciones quieres mostrar?"

es "3 publicaciones"
pt "3 posts"
en "3 posts"
es_mx "3 publicaciones"

es "6 publicaciones"
pt "6 posts"
en "6 posts"
es_mx "6 publicaciones"

es "9 publicaciones"
pt "9 posts"
en "9 posts"
es_mx "9 publicaciones"

es "Mostrar la cantidad de <em>‘Me gusta’</em> de cada publicación"
pt "Exibir quantidade de <em>“Likes”</em> de cada post"
es_mx "Mostrar los <em>‘Me gusta’</em> de cada publicación"

Activación

Por último podés activar las publicaciones de Instagram desde el Administrador nube, en la sección de Personalizar tu diseño actual dentro de Redes sociales:

Si necesitas ayuda para configurar la cuenta de instagram, podés visitar este post con más ayuda: ¿Cómo mostrar mis publicaciones de Instagram en mi Tienda Nube?