Primeiro, um pouco ofensivo :) Cedo ou tarde, qualquer loja online tem a questão de montar uma cesta abandonada. As estatísticas e a sensação de perda de dinheiro sugando o estômago não poupam ninguém.
Porcentagem de cestas abandonadas de 2006 a 2017
FontePorcentagem de cestas abandonadas no primeiro trimestre de 2018 por setor:
FonteAo mesmo tempo, apesar das estatísticas geralmente disponíveis, a maioria das lojas on-line não usa os recursos disponíveis e não conecta uma cesta abandonada. Um recente estudo "em casa" da EmailSoldiers mostra claramente que a maioria das lojas não se preocupa com isso.
Estatísticas atuais de cestas abandonadas conectadas
FonteAo mesmo tempo, todos (e nós também não somos santos) acompanham o tráfego, exibem anúncios e criativos, mas nem tentam devolver a pessoa que quebrou no último momento.
Porém, na primeira iteração, você pode obter um aumento de pedidos usando uma carta sem conteúdo dinâmico, basta configurá-la. Faça um esforço apenas uma vez para que, em segundo plano, traga dinheiro - isso não é um conto de fadas?
Naturalmente, uma carta com conteúdo dinâmico no qual os produtos da cesta são puxados pode funcionar melhor. Ou talvez outro gatinho com olhos tristes seja mais influente para o seu público. Ou você puxa as mercadorias recomendadas para as que estão na cesta e vê que elas são compradas com mais frequência por meio de cartas e aumenta a verificação média. Ou então, você poderá criar uma série de cartas a partir das quais a conversão será ainda maior.
Você pode melhorar e testar letras de uma cesta abandonada para um ideal inatingível, mas qualquer letra configurada já é incomparavelmente melhor que nada.
Conversão para uma cesta abandonada de acordo com RetailRocket
FonteE assim, o camarada
Artem Aleksandrov e eu começamos a introdução da cesta por dois lados.
Implementação técnica
TOR para integração
Descreva brevemente a essência da tarefa.
Tarefa: conectar um carrinho abandonado para o site xxx.xx ao serviço de correio Mailchimp
Distribuímos todos os materiais necessários.
Chave da API: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-usXX
Onde conseguir a chave?

→
Damos um link para a documentaçãoID da planilha à qual conectamos a Loja: XXXXXXXXXX
Onde posso obter o ID da planilha?

Um serviço de correio deve ser criado com antecedência. Assim que a solicitação da API é recebida pelo serviço de correspondência, a mensagem é gerada automaticamente e o destinatário é adicionado à fila para envio.
Para o nosso caso, escolhemos a seguinte lógica para enviar uma cesta abandonada:
Se um usuário autorizado no site adicionar mercadorias à cesta, não concluir a transação e não concluir o pedido, a cesta permanecerá inalterada por 1 hora. Depois disso, uma solicitação é enviada ao Mailchimp, no qual são transmitidos o email, a composição do pedido do usuário, imagens do produto, preço dos produtos e um link para a cesta do usuário.
Modelo de Layout
Ao criar automação para uma cesta abandonada, o mailchim pergunta imediatamente se haverá uma letra ou várias e sugere a escolha de uma loja conectada.

Nos modelos básicos, o mch oferece três opções de escolha:

- Cesta abandonada com mercadorias dinâmicas
- Cesta abandonada com recomendações de compras (precisa ser configurada separadamente)
- Cesta abandonada sem mercadorias (apenas uma carta)
Nas melhores tradições, se tiver tempo, você mesmo pode fazer a cesta.
Os produtos dinâmicos sem estilos são mais ou menos assim (esqueça a indentação, eles são mostrados aqui):
<table> <tbody> *|ABANDONED_CART:[$total=3]|* <table> <tbody> <tr> <td> <a href="*|CART:URL|*" title="*|PRODUCT:TITLE|*" target="_blank"> <img src="*|PRODUCT:IMAGE_URL|*"> </a> </td> <td> *|PRODUCT:TITLE|* — *|PRODUCT:PRICE|* </td> </tr> </tbody> </table> *|END:ABANDONED_CART|* </tbody> </table> *|END:ABANDONED_CART|* </tbody> </table>
Parece que se você alterar o número na variável
* | ABANDONED_CART: [$ total = 3] | * , a letra exibirá uma quantidade diferente de mercadorias, mas não, coloque pelo menos 5, pelo menos 100, o mch se recusará a mostrar outra quantidade.
E, o que também é um pouco estranho, a variável
* | PRODUCT: PRICE | * é substituída pelos valores de formato RUB288 e, por algum motivo, também é impossível mudar isso, mas mais adiante.
Para variar, tentamos substituir variáveis pelo número de jogos e pelo custo total do pedido, que transmitimos via API, mas o mailchimp aqui disse que não. Bem, que assim seja.
Uma palavra para o programador :)
Com o mailchimp, houve uma experiência histórica de integração com o mandril de serviço de terceiros, tudo é simples e claro lá. Documentação muito amigável (é claro, em inglês), mas não havia arestas e funcionou desde o primeiro chute.
Além disso, um mecanismo de inscrição através de formulários especiais foi introduzido em nosso site. Aqui, sentimos plenamente o eufemismo e a ambiguidade da documentação do mailchimp. O inglês não é um problema para um desenvolvedor experiente, mas o conhecimento do dialeto klingon não está implícito por padrão.
Os dados iniciais são: a linguagem php7 e a estrutura yii2, que já cresceu muito com seu ecossistema. I.e. Já temos seis pequenos projetos que estão tentando usar componentes comuns no backend e no front-end. Consequentemente, a implementação de qualquer tarefa requer a solução independente de seu projeto, mas isso não implica independência da estrutura, porque você tem que pagar por isso com horas humanas, das quais há sempre uma escassez.
Tendo recebido a tarefa de integração, devemos primeiro olhar em volta. O que nos é dado? Em primeiro lugar, o serviço mailchimp com o qual você precisa fazer amizade. Vamos ao github e vemos que existem muitas implementações. Mas a escolha é simples - o pacote mais popular de 1,5 mil estrelas (
drewm / mailchimp-api ).
O pacote fornece um invólucro simples sobre a interação restante com um chimp de correio. Só podemos adquirir isso com nossa lógica.
Em segundo lugar, recebemos
documentação . Com base na documentação, temos um recurso de loja com recursos aninhados: regra de carrinho, cliente, pedido, produto e promoção. Para uma cesta abandonada sem produtos recomendados, precisamos apenas de Produto, Carrinho e Cliente. O carrinho, por sua vez, consiste no conjunto de linhas do carrinho e o produto contém variantes do produto.
Decompusemos a tarefa da seguinte maneira:
- Carregar dados da loja para lojas
- Faça o download de todos os produtos compráveis em Produtos
- Configurar o carregamento de cestas com usuários em uma programação
Ok, vamos lá. Antes de tudo, assumimos a essência da "loja". Decidimos usar imediatamente a versão de teste e combate da loja e, dependendo da variável de ambiente responsável pelo modo de donzela / prod, trabalhamos com uma loja ou com outra.
Para baixar dados da loja, fazemos uma solicitação de postagem em / ecommerce / stores com o seguinte conjunto de parâmetros:
[ 'id' => 'dev.***.ru', 'list_id' => '****', 'name' => '*** - test', 'domain' => 'dev.***.ru', 'email_address' => 'admin@***.ru', 'currency_code' => 'RUB', 'primary_locale' => 'ru', 'money_format' => '₽', ]
Existem várias outras opções, mas tudo depende das necessidades. Porque não íamos usar os detalhes de contato da loja em cartas, não preenchemos os campos de telefone, endereço, fuso horário etc.
Mas uma pequena surpresa nos esperava. O campo money_format parece ter sido criado especialmente para a capacidade de apresentar o preço em um formato conveniente para nós. Mas, ao criar um modelo de cesto abandonado, o email substitui teimosamente o RUB antes do número. Mailchimp, pare com isso!
Após o download, podemos verificar os dados usando a solicitação de recebimento no endereço / comércio eletrônico / lojas para ver todas as lojas carregadas ou / ecommerce / stores / {id} para obter dados em uma loja específica.
Agora você pode adicionar todos os outros dados, porque a Loja é o ponto raiz da nossa árvore de dados, porque enviaremos todos os outros dados para uma loja específica.
Portanto, para que o MCH possa substituir produtos em uma cesta abandonada, ele precisa alimentar esses produtos. Para isso, temos o endereço / ecommerce / stores / {store_id} / products, para o qual enviamos solicitações posteriores para a criação de produtos no sistema.
[ 'id' => '742', 'title' => '', 'handle' => 'kastrulya', 'url' => 'http://***.ru/catalog/kastrulya/', 'description' => ' — . , . , ! !', 'type' => '', 'vendor' => ' ', 'image_url' => 'http://***.ru/images/742/product.png', 'variants' => [ [ 'id' => '742', 'title' => '', 'url' => 'http://***.ru/catalog/kastrulya/', 'price' => 890, 'sku' => 'KA453', 'inventory_quantity' => 1000, 'image_url' => 'http://***.ru/images/742/product.png', 'visibility' => 'visible', ], ], ]
O que é tão notável? Bem, primeiro, cada produto deve consistir em pelo menos uma oferta de produto. Essencialmente, o Produto é um contêiner para carregar ofertas de produtos. Além disso, o ID do produto e a oferta do produto podem se cruzar, porque esses são recursos diferentes na API do MCH.
E aqui começou o eufemismo da documentação do MCH. Eu tinha que adivinhar, mesmo que não fosse difícil, mas você poderia fazê-lo normalmente, e nem sempre.
O campo do identificador foi descrito como "o identificador de um produto". Ok, após a consulta, decidimos que isso faz parte do URL relacionado ao próprio produto (cnc). Mas isso foi confirmado apenas durante os testes.
Você também pode anexar uma série de fotos ao produto, mas decidimos que isso não seria útil para nós e, portanto, apenas a imagem principal foi carregada no produto e em cada oferta do produto.
E aqui tivemos um problema, por algum motivo as mercadorias não apareceram nos modelos de gráfico de correio.
Começamos a cavar a doca para o Produto. E eles encontraram um campo de visibilidade com uma descrição luxuosa:

Bem, digite String! E o que pode ser transferido para lá? Por que é impossível descrever todos os significados possíveis ?! Posso enviar para lá, por exemplo, "mostre-me pls!".
Felizmente, há um exemplo de solicitação!

Bem, isso não cancela o problema. Não sei que outros valores podem ser úteis.
Todo mundo lidou com isso! Agora, o profissional de marketing por email pode verificar a disponibilidade de mercadorias no sistema através da criação de um modelo com a participação de mercadorias ou todas as mesmas solicitações de obtenção usando o console.
Em seguida, somos confrontados com a tarefa de carregar cestas abandonadas no MCH. Inicialmente, duas opções vieram à mente:
- Cada vez que você altera a cesta (adicionar / remover mercadorias), repetimos essa ação no MCH. Das desvantagens - um grande número de solicitações para um serviço externo sugere-se imediatamente.
- Uma vez a cada n minutos, observe cestas que não foram alteradas há mais de uma hora. Então nós os enviamos para o MCH. Há apenas um problema - acompanhar as cestas que foram retomadas depois que foram para o MCH.
Primeiro, solicitamos ao nosso banco de dados (doravante denominado DB) nossos dados em uma janela de 1 hora a 3. Por que 3? Uma hora após a última alteração, enviamos a cesta para o sistema. No MCH, o intervalo mínimo possível para o envio da cesta é de 1 hora. Portanto, em teoria, após 2 horas ± 5 minutos, uma carta será enviada. Portanto, 3 horas é um valor, mesmo com uma margem.
Depois de receber os dados do banco de dados, solicitamos get no endereço / ecommerce / stores / {store_id} / carrts. Assim, obtemos todas as cestas que estão no sistema de comércio eletrônico e aguardamos a sua vez de enviar (ou já foram enviadas). Por que precisamos disso? É necessário sincronizar com nossos dados. Enviaremos todas as cestas recebidas do banco de dados, mas precisamos excluir as que não estiverem mais no intervalo de 1 a 3 horas. Depois de 3x - dados já irrelevantes. Até uma hora - cestas que podem ser renovadas novamente ou fazer um pedido.
Para excluir, basta encontrar a diferença entre as duas matrizes / coleções de cestas.
Depois de receber as cestas que precisam ser excluídas, enviamos uma solicitação de exclusão / ecommerce / stores / {store_id} / carrts / {cart_id}.
Em seguida, pegamos as cestas para download e as enviamos por pós-solicitações ao sistema em um ciclo.
Os parâmetros do carrinho são mais ou menos assim:
[ 'id' => '1207', 'customer' => [ 'id' => '25', 'email_address' => 'email@example.com', 'opt_in_status' => false, ], 'currency_code' => 'RUB', 'order_total' => 1597, 'checkout_url' => 'http://***.ru/cart/abandoned/?cart=eyJpdGVtcyI6eyI1OTgwIjoxLCIzNDA0IjoxLCI3NzMiOjEsIjkwNTgiOjEsIjkwOTEiOjEsIjE4ODciOjEsIjc4NCI6MSwiNTExMSI6MSwiODA1MyI6MSwiMTk0MSI6MSwiNTQ0NSI6MSwiNzk1NCI6MywiOTA2NyI6NCwiOTA2NSI6NCwiNzg0MyI6MSwiOTA2NiI6M30sInByb21vY29kZSI6bnVsbH0%253D', 'lines' => [ 0 => [ 'id' => '123', 'product_id' => '5980', 'product_variant_id' => '5980', 'quantity' => 1, 'price' => 841, ], 1 => [ 'id' => '124', 'product_id' => '3404', 'product_variant_id' => '3404', 'quantity' => 1, 'price' => 756, ], ], ]
? Carrinho //***.ru/cart/abandoned/ = eyJpdGVtcyI6eyI1OTgwIjoxLCIzNDA0IjoxLCI3NzMiOjEsIjkwNTgiOjEsIjkwOTEiOjEsIjE4ODciOjEsIjc4NCI6MSwiNTExMSI6MSwiODA1MyI6MSwiMTk0MSI6MSwiNTQ0NSI6MSwiNzk1NCI6MywiOTA2NyI6NCwiOTA2NSI6NCwiNzg0MyI6MSwiOTA2NiI6M30sInByb21vY29kZSI6bnVsbH0% 253D', [ 'id' => '1207', 'customer' => [ 'id' => '25', 'email_address' => 'email@example.com', 'opt_in_status' => false, ], 'currency_code' => 'RUB', 'order_total' => 1597, 'checkout_url' => 'http://***.ru/cart/abandoned/?cart=eyJpdGVtcyI6eyI1OTgwIjoxLCIzNDA0IjoxLCI3NzMiOjEsIjkwNTgiOjEsIjkwOTEiOjEsIjE4ODciOjEsIjc4NCI6MSwiNTExMSI6MSwiODA1MyI6MSwiMTk0MSI6MSwiNTQ0NSI6MSwiNzk1NCI6MywiOTA2NyI6NCwiOTA2NSI6NCwiNzg0MyI6MSwiOTA2NiI6M30sInByb21vY29kZSI6bnVsbH0%253D', 'lines' => [ 0 => [ 'id' => '123', 'product_id' => '5980', 'product_variant_id' => '5980', 'quantity' => 1, 'price' => 841, ], 1 => [ 'id' => '124', 'product_id' => '3404', 'product_variant_id' => '3404', 'quantity' => 1, 'price' => 756, ], ], ]
E, novamente, nossa rubrica favorita é "adivinhe como esses campos funcionam". Por exemplo, pelo método de cutucada científica, foi revelado que é possível não criar um comprador com uma solicitação separada. É necessário transferir o conjunto mínimo necessário de campos e ele será criado automaticamente se não estiver no sistema. No nosso caso, nos limitamos a id, email, opt_in_status. O último parâmetro é responsável pelo status da assinatura do usuário em nossa planilha. Se for verdade, isso significa que o estado está inscrito, caso contrário transacional.
A lista de produtos é carregada sem problemas pela matriz Cart Lines, que por sua vez é um recurso da entidade Cart. I.e. podemos gerenciar esse conjunto separadamente com solicitações de descanso.
Bem, isso é tudo, parece? Mas não.
Ao testar, notamos que o envio da mesma cesta é enviado apenas uma vez. Embora o tenhamos removido do sistema e baixado novamente. Nada é dito em lugar algum, nem uma única palavra! Como resultado, empiricamente, com a ajuda de uma mãe, tomamos como base a hipótese de que uma cesta com o mesmo id pode ser enviada apenas uma vez.
Aqui, concordo plenamente com os criadores de conteúdo que essa restrição nos salva de usuários de spam. Mas escreva sobre isso! Não precisamos de missões, temos o suficiente de nossos erros místicos no código que escrevemos.
Depois de tudo isso, o MCH começou a nos enviar lindas cartas sobre a cesta abandonada. E então uma segunda pergunta apareceu. Se o usuário jogou a cesta e retornou da carta para sua própria conta, ou seja, ele foi autorizado no momento de clicar no link, ele entrará na cesta sem problemas. E assim acontece que a carta diz “ligado! leve sua cesta de volta! ”, e quando a atravessamos, dizemos:“ Opa, algo estava perdido! Nós não tocamos em nada! É ele próprio! "
Decidiu-se codificar a composição da cesta em uma sequência e passá-la para checkout_url ao enviar a cesta ao MCH. E quando você for ao site, pegue essa linha, decodifique e jogue todas as mercadorias na cesta, sem esquecer de redefini-la completamente antes disso.
Portanto, não importa para qual navegador enviamos o usuário, ele recebe sua cesta, como prometemos. O único aspecto negativo é que ele só pode fazer login. Mas autorizar por meio de um link é uma má educação e, na verdade, é um negócio perigoso, antes de tudo para nossos clientes.
Qual é o resultado? Em princípio, não houve problemas específicos durante a implementação, pois muitas vezes as respostas do MCH ajudavam com erros relacionados à validação dos campos transferidos. Mas haveria ainda menos deles se eles normalmente descrevessem humanamente todas essas sutilezas do trabalho da MCH e descrevessem os campos com mais detalhes.
Configuração de relatório no Google.Analytics
Para acompanhar o sucesso de toda a operação, você precisará configurar e analisar periodicamente o relatório na análise. Imagine que todos, como adultos, tenham comércio eletrônico conectado, caso contrário, um milagre não funcionará :)
Para coletar um novo relatório para uma cesta abandonada, vá para "Meus relatórios":

Mais "Adicionar relatório":

E depois disso, adicionamos os parâmetros que rastrearemos. Decidimos que olharíamos para a cesta abandonada no contexto das cidades; você pode ter uma visão diferente.
Para um mailchamp, a campanha padrão para uma cesta abandonada é ABANDONED_CART_EMAIL, nós a substituímos no filtro e obtemos um relatório.

Isso é tudo garfos!
Agora você está configurado para enviar a cesta abandonada e um relatório pelo qual você pode assistir a exaustão dela. E teste, teste, teste! ;)