O widget cobre maioria dos casos out of the box. Este artigo cobre opções de customização mais profundas.
Variáveis CSS
O widget expõe variáveis CSS pra sobrescrever:
| Variável | Default | Propósito |
|---|---|---|
--mm-primary-color | #1a1813 | Cor de botão e acento |
--mm-primary-fg | #fff | Texto sobre cor primária |
--mm-bg | #fff | Background do widget |
--mm-fg | #1a1813 | Cor de texto default |
--mm-muted-fg | #5a5550 | Texto secundário |
--mm-border | #e5e1d8 | Bordas de cards |
--mm-radius | 1rem | Border radius |
--mm-font-family | system-ui | Tipografia |
--mm-spacing | 1rem | Densidade de padding |
--mm-shadow | minimal | Sombra de cards |
Setar no container div:
<div id="movementors-embed" style="
--mm-primary-color: #c4533c;
--mm-radius: 0;
--mm-font-family: 'Helvetica Neue', sans-serif;
"></div>
Ou na stylesheet do site:
#movementors-embed {
--mm-primary-color: #c4533c;
--mm-radius: 0;
}
Múltiplos widgets por página
Pode ter múltiplas instâncias na mesma página. Cada uma precisa container ID único e data-target correspondente.
<script src="https://movementors.com/embed.js" data-studio="seu-slug" data-mode="single" data-class="yoga-flow" data-target="mm-featured" async></script>
<div id="mm-featured"></div>
<!-- em outro lugar da mesma página -->
<script src="https://movementors.com/embed.js" data-studio="seu-slug" data-mode="list" data-target="mm-full-list" async></script>
<div id="mm-full-list"></div>
Ambos compartilham o mesmo script load (browser dedupes), mas renderizam em seus containers.
Filtrar a vista embedded
A página de config do widget permite filtrar o mostrado. Também pode sobrescrever via data-*:
| Atributo | Efeito |
|---|---|
data-location | Filtra a um slug de localização específico |
data-category | Filtra a slug de categoria (ex. "yoga") |
data-teacher | Filtra a um professor (slug platform ou ID custom) |
data-limit | Cap do número de aulas |
data-from | Aulas que começam após data (ISO) |
data-to | Aulas que começam antes da data |
Exemplo: widget homepage mostrando só "próximos 7 dias" de yoga na sua localização principal:
<script src="https://movementors.com/embed.js"
data-studio="seu-slug"
data-mode="grid"
data-category="yoga"
data-location="main-studio"
data-limit="6"
async></script>
<div id="movementors-embed"></div>
Event tracking
O widget dispara eventos custom que pode escutar:
movementors:loaded: DOM do widget pronto.movementors:class-viewed: user clicou card.movementors:booking-started: user abriu form de reserva.movementors:booking-completed: reserva exitosa.movementors:booking-failed: reserva falhou.
Escutar:
window.addEventListener('movementors:booking-completed', (e) => {
console.log('booking completed', e.detail);
// e.detail contém: { bookingId, classId, classTitle, amountCents, currency }
});
Útil pra:
- Google Analytics: disparar conversion event ao completar reserva.
- Facebook Pixel: trackear booking completions.
- Analytics interno: log pro seu backend.
Integração CSP
Se seu site tem Content Security Policy, deve permitir MoveMentors nestas diretivas:
Content-Security-Policy:
script-src 'self' https://movementors.com;
frame-src https://movementors.com;
connect-src 'self' https://movementors.com https://api.stripe.com;
img-src 'self' https://*.movementors.com https://res.cloudinary.com data:;
O widget usa iframe sandboxing internamente; seu CSP só precisa permitir o framing.
Authentication handoff
O widget suporta "preauth": se um user já está logado no seu site, pode passar pro MoveMentors sem re-perguntar nome e email.
<script src="https://movementors.com/embed.js"
data-studio="seu-slug"
data-prefill-name="Jane Doe"
data-prefill-email="jane@example.com"
async></script>
<div id="movementors-embed"></div>
Os valores pré-preenchem o form. User pode editar; isso é conveniência, não boundary de segurança. (Não assuma que user está "logado" só porque pré-preencheu; a reserva real ainda requer confirmação de email.)
Server-side rendering
O widget é client-side only. Não tem versão SSR que emite HTML pra SEO.
Se quer que sua página de reservas seja indexada por buscadores com conteúdo completo visível, linke pras páginas de detalhe de aula do MoveMentors (que SÃO SSR) em vez de depender do widget pra SEO.
Pra "próximas 5 aulas" visível a crawlers, considere também linkar pro diretório MoveMentors; o widget dá UI de reserva, o link dá SEO juice.
Performance
Bundle pesa ~80KB gzipped. Carrega async (atributo async) então não bloqueia render da sua página.
Render inicial: ~1-2 segundos em conexão decente.
Após carregar:
- Interações de cards: instantâneas (estado client).
- Abertura do form: instantânea.
- Submit: depende do método de pagamento (Stripe Checkout adiciona ~1 segundo de overhead de redirect).
Se seu site é performance-critical, considere lazy-load (montar o widget só após interação). Padrão:
<button id="open-booking">Browse classes</button>
<div id="movementors-embed"></div>
<script>
document.getElementById('open-booking').addEventListener('click', () => {
const s = document.createElement('script');
s.src = 'https://movementors.com/embed.js';
s.dataset.studio = 'seu-slug';
s.async = true;
document.body.appendChild(s);
});
</script>
Widget carrega só no click. Trade-off: pequeno delay extra pra users que clicam.
Considerações móveis
Widget é responsive. Adapta:
- Layout single-column abaixo de 640px.
- Tap targets touch-friendly (44×44 min).
- Form usa teclados móveis nativos (numérico pra preços, email pra emails).
Se seu site tem layout mobile específico, o widget pode configurar por layout: use data-mode distintos em script desktop vs mobile, gateados por media queries CSS.
Perguntas comuns
Posso ter versão full white-label com meu logo e sem branding MoveMentors? Customers Enterprise podem pedir. Default inclui pequeno footer "powered by MoveMentors".
Posso rodar o widget em múltiplos domínios? Sim. O widget não whitelista domínios. Qualquer um com seu slug pode embedar.
Posso prevenir que outros embedem meu widget? Não atualmente. Widget puxa data pública de aulas; qualquer um que saiba seu slug pode embedar. Podemos adicionar domain allow-listing como feature Enterprise.
Posso customizar os campos do form? Não atualmente. Os campos são os mesmos do site. Customização de campos em roadmap.
Reservas do widget contam pra minha visibilidade / ranking? Sim. Reserva é reserva independente da fonte. Reservas do embed contam pros totais do seu studio, reviews agregam igual, etc.
Próximos passos
- Embed widget: básicos.
- Embed widget não carrega: diagnóstico.