Documentazione API
Lo Shoppi SDK, l'API JSON e i TagCode: tutto quello che serve a un partner per costruire su un negozio Shoppi.
Come funziona
Ogni negozio su Shoppi Cloud si estende con lo Shoppi SDK, una libreria JavaScript servita dalla piattaforma su ogni dominio ospitato da Shoppi, e con i TagCode, segnaposto lato server che il motore delle pagine risolve prima che la pagina arrivi al browser. Entrambi parlano con la stessa API JSON, usabile anche direttamente.
- Nessuna chiave API nel browser. Il negozio si riconosce dal dominio da cui parte la richiesta: l'SDK funziona sul dominio del negozio senza segreti nel codice.
- I pagamenti passano da Stripe. Le sessioni di checkout nascono sull'account Stripe del merchant (Stripe Connect); Shoppi non tocca mai i soldi dei clienti del merchant. Anche i rimborsi passano tutti da Stripe.
- Due database. Il catalogo si legge dal database Shoppi, quello che il merchant gestisce dall'app; ogni dominio di negozio ha anche un database suo. Scegli tu da quale legge ogni API (vedi Catalogo). Gli account dei clienti stanno sempre nel database del dominio del negozio, separati dagli altri negozi.
- Versione attuale dell'SDK: 2.9.0. Le risposte hanno sempre la stessa forma:
{"result": "ok" | "ko", "feedback": …}.
Installazione
Includi l'SDK una volta, nel <head> della pagina. Al caricamento crea l'oggetto globale window.Shoppi.
<script>
window.ShoppiConfig = {
pageId: "%_ID%", // store id; the page engine fills it in (use %_ID% inside JS, not {id})
currency: "EUR", // default currency for cart and checkout
defaultLocale: "it", // language used when the URL has no /xx/ prefix
baseUrl: "", // leave empty: API calls go to the same origin
sources: "shoppi" // catalog database: "shoppi" (default) or "local"
};
</script>
<script src="/shoppi/shoppi-sdk.js?v=2.9.0"></script>
Tutte le impostazioni sono facoltative: senza ShoppiConfig l'SDK riconosce il negozio dal dominio e usa l'euro. Aumenta il parametro ?v= quando vuoi che i browser scarichino un SDK più recente.
Negozio e contenuti — Shoppi.site
| Metodo | Restituisce |
|---|---|
Shoppi.site.getInfo() |
Profilo del negozio: nome, logo, copertina, descrizione, categoria, città, paese, lingua. |
Shoppi.site.getPage(slug) |
Una pagina di contenuto dal suo slug: titolo, contenuto HTML e parole chiave, oppure null. |
Shoppi.site.getPages() |
Le sezioni del negozio: pagine di contenuto e categorie a cui appartengono i prodotti. |
Shoppi.site.getProducts(options) |
Come Shoppi.catalog.products(). |
Shoppi.site.getProduct(idOrSlug) |
Come Shoppi.catalog.product(). |
Shoppi.site.getCategories() |
Come Shoppi.catalog.categories(). |
Shoppi.site.search(q) / getSuggestions(q) |
Come Shoppi.catalog.search() e suggestions(). |
const info = await Shoppi.site.getInfo();
document.getElementById('store-name').textContent = info.title;
Catalogo — Shoppi.catalog
Prodotti, categorie, foto e ricerca: i dati che il merchant gestisce dall'app Shoppi, pronti per costruire una vetrina. Ogni articolo arriva nella stessa forma, qualunque sia il tipo:
{
id: 9610389, type: 'products', // products | services | files | offers
slug: 'curtirisorisobasmati2×500g',
title: 'Curtiriso Riso Basmati 2 × 500 g',
description: '', content: 'Basmati', // content may contain HTML
price: 4.79, currency: 'EUR', price_format: '4,79 €',
photo: 'https://storage.shoppi.app/…', photo_hires: '…', photos: ['…'],
quantity: 5, in_stock: true, ship_cost: 0, code: 'CX-DIS-000001',
category: 'Dispensa', keywords: ['dispensa'], link: '…', date: 1791312283
}
| Metodo | Restituisce |
|---|---|
Shoppi.catalog.products(options) |
Restituisce { items, count, limit, skip, hasMore }. Opzioni: type (products, services, files, offers, all), limit (24), skip, sort (newest, updated, popular, price_asc, price_desc, title), category (id, slug o titolo), q, ids, inStock. |
Shoppi.catalog.product(idOrSlug, { type }) |
Un articolo, oppure null. Un articolo di un altro negozio non viene mai restituito. |
Shoppi.catalog.categories({ type }) |
sections (predefinito: le categorie a cui sono agganciati i prodotti), albums o tree. |
Shoppi.catalog.category(ref) |
Una categoria per id, slug o titolo. |
photos(), pages(), page(slug), news(), videos() |
I contenuti del negozio. |
Shoppi.catalog.search(q, { type, limit, minPrice, maxPrice }) |
Restituisce { items, count, suggestions, did_you_mean }. |
Shoppi.catalog.suggestions(q) |
Titoli per un autocompletamento. |
Shoppi.catalog.info() |
Profilo del negozio. |
const page = await Shoppi.catalog.products({ limit: 12 });
const cats = await Shoppi.catalog.categories(); // [{ id: 600, slug: 'dispensa', title: 'Dispensa' }, …]
const food = await Shoppi.catalog.products({ category: 'dispensa' });
const one = await Shoppi.catalog.product(9610389); // or by slug
const hits = await Shoppi.catalog.search('riso'); // { items, count, suggestions }
Quale database: per API, per chiamata
'shoppi' (predefinito) legge il database Shoppi, dove il merchant gestisce i prodotti dall'app. 'local' legge il database del dominio del negozio, vuoto finché non ci scrivi. Scegli per API in ShoppiConfig.sources, a runtime con Shoppi.catalog.use() o per una sola chiamata con { source }. Una sorgente può anche essere l'URL base di un altro host o una funzione che restituisce dati tuoi. Carrello, checkout, account clienti ed email girano sempre sul dominio del negozio.
window.ShoppiConfig = {
pageId: "%_ID%",
sources: { products: 'shoppi', categories: 'local' } // or one value: 'local'
};
Shoppi.catalog.use('search', 'local'); // at runtime, one API
await Shoppi.catalog.products({ limit: 12 }, { source: 'local' }); // for one call
Rendering ed eventi
Shoppi.render(target, items, template) riempie un elemento con una lista: il template è una funzione, una stringa Handlebars, oppure niente per la scheda integrata con il pulsante aggiungi al carrello. Gli elementi con data-shoppi-list si riempiono da soli al caricamento della pagina; gli altri attributi data-shoppi-* sono le opzioni del metodo corrispondente. Eventi su document: shoppi:cart:added, shoppi:cart:updated, shoppi:checkout:started, shoppi:rendered.
const r = await Shoppi.catalog.products({ limit: 12 });
Shoppi.render('grid', r); // built-in card with add-to-cart button
Shoppi.render('grid', r, p => `<h3>${p.title}</h3><p>${p.price_format}</p>`);
<div data-shoppi-list="products" data-shoppi-limit="12" data-shoppi-category="dispensa">
<template><div class="card"><img src="{{photo}}"><h3>{{title}}</h3>
<button data-shoppi-add="{{id}}" data-shoppi-price="{{price}}"
data-shoppi-title="{{title}}" data-shoppi-image="{{photo}}">Add</button></div></template>
</div>
document.addEventListener('shoppi:cart:added', e => console.log(e.detail.title));
Carrello — Shoppi.cart
Il carrello vive nel browser (localStorage) e resta dopo il ricaricamento. Prezzi e titoli che passi arrivano fino al checkout, quindi impostali sempre.
| Chiamata | Cosa fa |
|---|---|
Shoppi.cart.add(id, qty, { price, title, image }) |
Aggiunge un prodotto (quantità predefinita 1). |
Shoppi.cart.updateQty(id, qty) |
Imposta la quantità; 0 toglie la riga. |
Shoppi.cart.remove(id) |
Toglie una riga. |
Shoppi.cart.clear() |
Svuota il carrello. |
Shoppi.cart.setCountry(code) |
Imposta il paese di spedizione (codice ISO, per esempio 'IT'). |
Shoppi.cart.data |
Stato attuale: { items, count, total, country }. |
Senza JavaScript, con gli attributi HTML:
<button data-shoppi-add="10034"
data-shoppi-price="29.90"
data-shoppi-title="Leather wallet"
data-shoppi-image="/img/wallet.jpg">Add to cart</button>
<span class="shoppi-cart-count"></span> <!-- item count, updated automatically -->
<span class="shoppi-cart-total"></span> <!-- total, formatted in the store currency -->
<select data-shoppi-country> <!-- shipping country -->
<option value="IT">Italia</option>
<option value="DE">Deutschland</option>
</select>
<button data-shoppi-checkout>Checkout</button>
Checkout — Shoppi.checkout
| Metodo | Cosa fa |
|---|---|
Shoppi.checkout.start() |
Crea una sessione Stripe Checkout per il carrello sull'account Stripe del merchant e ci porta il cliente. |
Shoppi.checkout.startDirect(productId, metadata) |
Acquisto in un clic di un solo prodotto, senza carrello (servizi, prenotazioni, download). |
Shoppi.checkout.createOnboardingLink() |
Restituisce il link di onboarding Stripe del negozio, per collegare o completare il suo account Stripe. |
document.querySelector('#buy').addEventListener('click', () => Shoppi.checkout.start());
// Stripe onboarding for the merchant
const url = await Shoppi.checkout.createOnboardingLink();
window.location.href = url;
Ogni pulsante con data-shoppi-checkout fa la stessa cosa di Shoppi.checkout.start(). I costi dei pagamenti seguono il piano del negozio: commissioni Stripe più l'app fee Shoppi Pay dello 0,4% + 1 centesimo per pagamento. Anche i rimborsi, totali o parziali, online o al POS, passano da Stripe.
Account clienti — Shoppi.user
Account per i clienti del negozio, salvati nel database del negozio. Dopo il login il token di sessione resta nel browser e viaggia con ogni richiesta dell'SDK nell'header X-User-Token. Gli account sono legati al dominio del negozio: due negozi non vedono mai i clienti l'uno dell'altro.
| Metodo | Cosa fa |
|---|---|
Shoppi.user.register(email, password, firstName, lastName) |
Crea un account ed esegue il login. |
Shoppi.user.login(email, password) |
Esegue il login. |
Shoppi.user.getProfile() |
Profilo del cliente collegato (null se non è collegato). |
Shoppi.user.updateProfile(data) |
Aggiorna i campi del profilo, per esempio { phone }. |
Shoppi.user.saveAddress(type, address) |
Salva un indirizzo; type è per esempio 'shipping'. |
Shoppi.user.logout() |
Chiude la sessione e ricarica la pagina. |
Navigazione e traduzioni — Shoppi.router, Shoppi.lang
Gli URL seguono lo schema /<language>/<page>, per esempio /it/contatti. Shoppi.router.navigate(slug, locale) carica una pagina senza ricaricare tutto e la mostra in <main>; i link con data-shoppi-link fanno lo stesso.
<a href="/it/contatti" data-shoppi-link="contatti">Contatti</a>
Shoppi.lang.load(locale) carica le traduzioni del negozio; Shoppi.lang.t(key, vars) restituisce una stringa e sostituisce i segnaposto scritti come %_NAME%.
Directory locale — Shoppi.local
| Metodo | Restituisce |
|---|---|
Shoppi.local.getCities() |
Città disponibili nella directory locale. |
Shoppi.local.getBusinesses(cityId, categoryId) |
Attività di una città, con filtro facoltativo per categoria. |
Email — Shoppi.mailer
Invia un'email transazionale dal negozio, per esempio da un modulo di contatto. Limite: 10 email al giorno per dispositivo.
await Shoppi.mailer.send({
to: '[email protected]',
subject: 'New request from the website',
body: '<p>Hello!</p>',
replyTo: '[email protected]' // optional
});
Shoppi.mailer.remaining(); // emails left today on this device
API JSON
Ogni metodo dell'SDK è una chiamata all'API JSON, che puoi usare direttamente con Shoppi.call(endpoint, params, method) o con un semplice fetch: lo schema è /api/<module>/<method>/json, sul dominio del negozio.
| Endpoint | A cosa serve |
|---|---|
GET /api/website/info/json |
Profilo del negozio |
GET /api/website/section/json?clear_title=<slug> |
Pagina di contenuto |
POST /api/checkout/createStripeSession/json |
Sessione Stripe Checkout da un carrello |
POST /api/checkout/startDirect/json |
Acquisto diretto di un prodotto |
GET /api/checkout/createOnboardingLink/json |
Link di onboarding Stripe |
POST /api/frontend_user/register/json |
Registrazione cliente |
POST /api/frontend_user/login/json |
Login cliente |
GET /api/local/getCities/json |
Directory locale: città |
GET /api/website/products/json |
Prodotti (anche listServices, listFiles, listOffers) |
GET /api/website/product/json?id= |
Un prodotto, per id o clear_title
|
GET /api/website/sections/json |
Sezioni e categorie |
GET /api/website/listSells/json?parent= |
Articoli agganciati a una sezione |
GET /api/search/results/json?query= |
Ricerca |
GET /api/search/suggestions/json?query= |
Autocompletamento |
const res = await fetch('/api/website/info/json', { credentials: 'include' });
const data = await res.json(); // { "result": "ok", ... } or { "result": "ko", "feedback": "reason" }
Gli endpoint del catalogo rispondono sul dominio del negozio (il suo database) e su https://shoppi.app (il database Shoppi). Per la sorgente 'shoppi' l'SDK chiama shoppi.app con l'id del negozio: un id che non appartiene al dominio chiamante viene rifiutato. Shoppi.call(endpoint, params, method, { base }) sceglie l'host.
Shoppi.call() restituisce la parte utile di una risposta ok e lancia un Error con il messaggio feedback quando la risposta è ko.
TagCode (lato server)
I TagCode sono segnaposto nei template HTML del negozio, risolti sul server prima di inviare la pagina: il contenuto sta nell'HTML che vedono i motori di ricerca.
| TagCode | Output |
|---|---|
{css} / {js}
|
Fogli di stile e script della pagina e dei suoi plugin |
{page_title}, {page_description}
|
Titolo e descrizione SEO |
{page_name}, {page_logo}
|
Nome e logo del negozio |
{locale}, {currency}, {country}
|
Lingua, valuta e paese del visitatore |
{title}, {content}, {photo}, {price}, {link}
|
Campi del prodotto o dell'articolo corrente |
{cfield:title}, {cfield:description}, {cfield:cover}
|
Campi del profilo del negozio |
{cart:act=drawer} |
Carrello a scomparsa laterale |
{search:nout=true} |
Ricerca, inizializzata senza output predefinito |
{cookieconsent} |
Banner del consenso cookie |
{offers:act=seo} |
Dati strutturati JSON-LD per i prodotti |
Dentro un oggetto JavaScript usa %_ID% per l'id del negozio: lì le graffe verrebbero lette come TagCode.
Accesso a file e dati
I file di ogni negozio sono raggiungibili via WebDAV (anche con l'app desktop Shoppi Go) e i dati restano esportabili: template HTML standard, il database del negozio e l'API JSON qui sopra. Le credenziali di accesso sono nel pannello account del negozio.
Domande o un caso che qui non trovi? Prenota una call con il team partner, oppure torna al kit partner.