Shopify Headless

Criada por Alex Camargo, Modificado em Seg, 29 Set na (o) 1:29 PM por Alex Camargo

Para incluir a BonifiQ via Shopify Headless é necessário que você inclua no template do Hydrogen alguns componentes e faça alguns ajustes para que o script da BonifiQ rode corretamente.


Libere o ContentSecurityPolicy

Adicione os seguintes itens ao ContentSecurityPolicy do seu entry.server.tsx

const { nonce, header, NonceProvider } = createContentSecurityPolicy({
    shop: {
      checkoutDomain: context.env.PUBLIC_CHECKOUT_DOMAIN,
      storeDomain: context.env.PUBLIC_STORE_DOMAIN,
    },
    scriptSrc: [
      "'self'",
      'https://cdn.shopify.com',
      'https://bq-scripts.s3.amazonaws.com',
      'https://widget.bonifiq.com.br',
    ],
    frameSrc: [
      'https://widget.bonifiq.com.br',
      'https://landingpage.bonifiq.com.br',
    ],
    imgSrc: [
      'https://bq-public-images.s3.amazonaws.com',
    ]
  });


Criar um novo componente para o script da BonifiQ

Esse componente adiciona o script da BonifiQ em todo o site. Crie um novo arquivo em /app/components/BqScript.tsx. Inclua o conteúdo abaixo:

import {CartReturn} from '@shopify/hydrogen';
import {useEffect} from 'react';

type Customer = {
  id?: string;
  email?: string | null;
  firstName?: string | null;
  lastName?: string | null;
};

type BqScriptProps = {
  bonifiqId: string;
  nonce?: string;
  cart?: Promise<CartReturn | null> | undefined;
  customer?: Promise<Customer | null>;
};

export function BqScript({
  bonifiqId,
  nonce,
  cart,
  customer,
}: BqScriptProps) {
  useEffect(() => {
    if (!bonifiqId) return;

    const src = `https://bq-scripts.s3.amazonaws.com/scripts/${bonifiqId}/bqloader.js`;
    let script: HTMLScriptElement | null = null;
    let cancelled = false;

    (async () => {
      const resolvedCustomer = customer ? await customer : null;

      // Prefer explicit props; fall back to cart.buyerIdentity
      let email: string | null | undefined = resolvedCustomer?.email;
      let id: string | undefined = resolvedCustomer?.id
        ? resolvedCustomer.id.split('/').pop()
        : undefined;
      const customerFullName =
        resolvedCustomer?.firstName || resolvedCustomer?.lastName
          ? `${resolvedCustomer.firstName ?? ''} ${
              resolvedCustomer.lastName ?? ''
            }`.trim()
          : undefined;
      let name: string | null | undefined = customerFullName;

      if ((!email || !id || !name) && cart) {
        try {
          const resolved = await cart; // <-- resolve the Promise<CartReturn | null>
          const bi: any = resolved?.buyerIdentity as any | undefined;

          // In Hydrogen, buyerIdentity has `email` and optional `customer`
          if (bi) {
            email = email ?? bi.email ?? bi.customer?.email ?? null;
            const c = bi.customer as
              | {
                  id?: string;
                  firstName?: string | null;
                  lastName?: string | null;
                }
              | undefined;

            if (c) {
              id = id ?? (c.id ? c.id.split('/').pop() : undefined);
              const firstName = c.firstName ?? null;
              const lastName = c.lastName ?? null;
              const fullName = `${firstName ?? ''} ${lastName ?? ''}`.trim();
              if (fullName) {
                name = name ?? fullName;
              }
            }
          }
        } catch (ex) {
          console.log('[BonifiQ] Error on customer resolution - ' + ex)
        }
      }

      if (cancelled) return;

      if (email) sessionStorage.setItem('bqemail', String(email));
      if (id) sessionStorage.setItem('bqid', String(id));
      if (name) sessionStorage.setItem('bqname', name);

      script = document.createElement('script');
      script.src = src;
      script.type = 'text/javascript';
      script.async = true;
      if (nonce) script.nonce = nonce;
      document.head.appendChild(script);
    })();

    return () => {
      cancelled = true;
      if (script && document.head.contains(script)) {
        document.head.removeChild(script);
      }
    };
    // Re-run if inputs change
  }, [bonifiqId, nonce, cart, customer]);

  return null;
}

 Adicione o componente ao root.tsx

Você precisa trocar o CODIGO_BONIFIQ pelo identificador fornecido pelo time da BonifiQ. Cada loja virtual/marca possui seu próprio código.

 <BqScript bonifiqId="CODIGO_BONIFIQ"
nonce={nonce}
cart={data?.cart}/>

Habilite o Single Sign On

Além de receber o cart, o componente da BonifiQ pode receber também um customer (com id, nome e e-mail). Esse customer deve representar o usuário logado na loja e permite que ele esteja automaticamente logado no Widget da BonifiQ.

Uma sugestão para isso, segue os seguintes passos:

- Adicione um novo arquivo "CustomerBasicQuery.ts" em /app/graphql/customer-account

export const CUSTOMER_QUERY = `#graphql
  query CustomerBasic {
    customer {
      id
      emailAddress {
        emailAddress
      }
      firstName
      lastName
    }
  }
`;

- Leia o customer no root.tsx

  const customerPromise = isLoggedInPromise
    .then(async (logged) => {
      if (!logged) return null;
      const res = await customerAccount.query(CUSTOMER_QUERY);
      const c = res?.data?.customer;
      if (!c) return null;
      return {
        id: c.id,
        email: c.emailAddress?.emailAddress ?? null,
        firstName: c.firstName ?? null,
        lastName: c.lastName ?? null,
      };
    })
    .catch((err) => {
      console.error('Failed to load customer', err);
      return null;
    });

  return {
    cart: cart.get(),
    isLoggedIn: isLoggedInPromise,
    customer: customerPromise, // Promise
    footer,
  };
}

- Informe o customer no BqScript

<Suspense>
          <Await resolve={data?.customer}>
            {(customer) => (
              <BqScript
                bonifiqId="493b22a9-aaa4-44ec-9760-29ad95326e54"
                nonce={nonce}
                cart={data?.cart}
                customer={customer}
              />
            )}
          </Await>
        </Suspense>


Adicione a Landing Page

Para isso, basta criar um novo arquivo em app/routes chamado ($locale).bq-landingpage.tsx (utilize o nome que desejar)

export default function BQLandingPage() {
  return (
    <div className="bq-landing-page">
      <div id="bq-landingpage"></div>
    </div>
  );
}
Para que a Landing Page funcione corretamente é necessário instalar o script (via componente) acima



Se precisar de referências/exemplos, verifique o nosso repositório:

https://github.com/bonifiq/bonifiq-shopify-headless/tree/main

Este artigo foi útil?

Que bom!

Obrigado pelo seu feedback

Desculpe! Não conseguimos ajudar você

Obrigado pelo seu feedback

Deixe-nos saber como podemos melhorar este artigo!

Selecione pelo menos um dos motivos
A verificação do CAPTCHA é obrigatória.

Feedback enviado

Agradecemos seu esforço e tentaremos corrigir o artigo