So erstellst du eine Mobile App für deinen Shopify-Shop mit React Native

So erstellst du eine Mobile App für deinen Shopify-Shop mit React Native
So erstellst du eine Mobile App für deinen Shopify-Shop

Wenn du einen Shopify-Shop hast, bist du wahrscheinlich bereits von der Leistungsfähigkeit der E-Commerce-Plattform überzeugt. Wenn du deinen Shop auf die nächste Stufe bringen willst, könnte eine Mobile App genau das sein, was du brauchst!

Der Vorteil einer App für deinen Shopify-Shop

Wenn du einen Webshop hast, der bereits gut funktioniert, fragst du dich vielleicht, ob du eine Mobile App brauchst. Deshalb schauen wir uns erst einmal die Vorteile einer solchen App an, denn davon gibt es viele!

Zunächst einmal macht der E-Commerce über das Handy, besser bekannt als M-Commerce, mehr als die Hälfte aller E-Commerce-Verkäufe aus. Und dieser Anteil wächst von Jahr zu Jahr! Es wird davon ausgegangen, dass dieser Anteil bis 2027 auf 62 % ansteigen wird.
(Quelle: Statista)

Statista-Grafik zur Entwicklung und Prognose des M-Commerce

Diese Grafik unterstreicht die Bedeutung des mobilen E-Commerce. Wenn du diesen Weg vernachlässigst, könntest du mehr als die Hälfte der potenziellen Umsätze verpassen und im Wettbewerb gegen deine Konkurrenz verlieren. Wenn deine Konkurrenten eine App haben und du nicht, haben sie einen Vorteil.

Doch es gibt auch noch andere Vorteile:

  1. Ein besseres Kundenerlebnis
    Es ist kein Zufall, dass jede große E-Commerce-Website ihre eigene mobile Anwendung hat. So kannst du deinen Kunden ein personalisiertes Erlebnis und eine bessere Zugänglichkeit zu deinem Shop bieten.
  2. Ein Kanal für direkte Kommunikation
    Wenn deine Kunden deine App installiert haben, kanst du ihnen Benachrichtigungen schicken und hast direkten Zugang zu ihnen. Das ist sehr viel effizienter als E-Mail-Newsletter.
  3. Besserer Datenzugang
    Wenn Nutzer:innen deine App verwenden, sind sie in der Regel eingeloggt, und du kannst und Nutzungsverhalten und Interessen besser erfassen und im Profil hinterlegen.

Jetzt, wo du davon überzeugt bist, dass die Erstellung einer Mobile App für deinen Shopify-Shop eine gute Idee ist, lass uns ansehen, warum React Native die beste Lösung dafür ist!

React Native, die beste Lösung für deine mobile E-Commerce-App

Wenn du Shopify bereits für deinen Shop vertraust, solltest du ihnen auch bei der Technologie-Auswahl vertrauen. Und React Native ist Shopifys erste Wahl wenn es um Frameworks für Mobile Apps geht.

Wie auf der React Native-Website zu sehen ist, nutzt Shopify das Framework intensiv für seine eigenen Anwendungen. Alle neuen Shopify-Apps werden mit diesem Framework erstellt und die bisherigen Apps werden aktiv zu React Native migriert, wie in diesem Artikel zu lesen ist.

Erstellen eines mobilen Shopify-Shops mit React Native

Kommen wir nun zum technischen Teil dieses Artikels! Wir werden uns anschauen, wie du mit deinem Shopify-Shop über eine React Native-App interagieren kannst. Wir werden eine vollständig angepasste Anwendung erstellen und alle Daten aus deinem Shop abrufen.

In deinem Shopify-Panel:

Zunächst musst du einen Storefront-API-Zugangstoken von Shopify generieren, um es mit deiner React Native-App zu verknüpfen. Folge dazu einfach diesen Schritten:

1 - Rufe dein Shopify-Panel auf und gehe zu Einstellungen (im unteren Teil der linken Seitenleiste).

2 - Wähle in den Einstellungen auf der linken Seite Apps und Vertriebskanäle und klicke auf Apps entwickeln.

Shopify-Panel-Einstellungen

3 - Klicke auf App erstellen, benenne deine App und bestätige. Daraufhin wird der Konfigurationsbereich geöffnet. In diesem Abschnitt kannst du die API-Zugriffsebenen auswählen.

Liste API-Zugang

4 - Zum Abschluss klickst du oben rechts auf App installieren. Sobald sie installiert ist, kannst du zu API-Zugangsdaten gehen, um das Storefront API access token zu erhalten.

Storefront API-Zugangstoken

Jetzt, wo du dein Storefront API access token hast, können wir zur React-Native-Anwendung übergehen!

In deiner React Native-Anwendung:

1 - Installieren wir zunächst das Shopify Buy SDK, mit dem wir die Daten aus deinem Shop in unserer App abrufen können. Führe dazu den folgenden Befehl aus:

npm install shopify-buy

Oder, wenn du yarn zur Verwaltung deiner Pakete verwendest:

yarn add shopify-buy

2 - Dann erstellen wir eine Datei für unsere Shopify-Funktionen, irgendwo in unserem src Ordner.
N.B.: Du kannst dein Projekt auch anders organisieren (ein Shopify-Ordner mit einer Datei für jede Funktion zum Beispiel).

import Client from 'shopify-buy';

const client = Client.buildClient({  
  domain: 'your-domain',
  storefrontAccessToken: 'your-store-front-access-token'
});

export async function fetchAllProducts() {
  return client.product.fetchAll();
}

export async function fetchSingleProduct(productId) {
  return client.product.fetch(productId);
}

3 - Jetzt kannst du von deiner Komponente aus auf die Funktion zugreifen, mit der du die Produkte laden möchtest, zum Beispiel Sales Channels:

import { fetchAllProducts } from '../shopifyFunctions';

interface Product {
  id: string;
  title: string;
  images: { src: string }[];
}

const [products, setProducts] = useState<Product[]>([]);

useEffect(() => {
  const fetchData = async () => {
    try {        
      const data = await fetchAllProducts();        
      setProducts(data);      
    } catch (error) {        
      console.error('Error fetching products: ', error);      
    }    
  };    
  fetchData() 
}, []);

Auflistung der Produkte aus deinem Shop

Sobald wir alle Produkte aus unserem Shop in unseren Komponenten-State geladen haben, können wir mit ihnen interagieren. Als Beispiel werden wir einfach unsere Produkte anzeigen und eine onPress() Funktion hinzufügen, um zu einer Detailansicht mit der Produkt-ID als Parameter zu navigieren. Zudem werden wir ein Default Bild hinzufügen, falls das Produkt kein Bild hat.

<SafeAreaView>
  <ScrollView
    contentContainerStyle={{
      alignItems: 'center',
      justifyContent: 'center',
    }}
  >
    {products.map((product) => {
      return (
        <TouchableOpacity
          key={product.id}
          onPress={() =>
            navigation.navigate('Details', { id: product.id })
          }
        >
           {product.images && product.images.length > 0 ? (
                <Image
                  source={{ uri: product.images[0].src }}
                />
              ) : (
                <Image
                  source={{
                    uri: 'https://st4.depositphotos.com/14953852/24787/v/450/depositphotos_247872612-stock-illustration-no-image-available-icon-vector.jpg',
                  }}
                />
              )}
          <Text>{product.title}</Text>
        </TouchableOpacity>
      );
    })}
  </ScrollView>
</SafeAreaView>

Screenshot der Testanwendung

Informationen über ein bestimmtes Produkt erhalten

Nun erstellen wir die Produkt-Detailseite. Dank der ID, die wir durch die Navigation übergeben, kann unsere Komponente das richtige Produkt mit Hilfe der fetchSingleProduct() abrufen, die wir im zweiten Schritt erstellt haben. So sieht diese Produktkomponente aus:

import { fetchSingleProduct } from '../shopifyFunctions';

interface Product {
  id: string;
  title: string;
  images: { src: string }[];
}

const Product: FunctionComponent<Props> = ({ route, navigation }) => {
  
  const { id } = route.params;
  const [product, setProduct] = useState<Product[]>([]);

  useEffect(() => {
      const fetchData = async () => {
        try {
          const data = await fetchSingleProduct(id);
          setProduct(data);
          setLoading(false);  
        } catch (error) {        
          console.error('Error fetching product: ', error);      
        } 
      };
    fetchData();
  }, []);

  return (
    <View>
      <View>
        {product.images && product.images.length > 0 ? (
          <Image
            source={{ uri: product.images[0].src }}
          />
        ) : (
          <Image
            source={{
              uri: 'https://st4.depositphotos.com/14953852/24787/v/450/depositphotos_247872612-stock-illustration-no-image-available-icon-vector.jpg',
            }}
          />
        )}
        <Text>
          {product.variants[0].price.amount}{' '}
          {product.variants[0].price.currencyCode}
        </Text>
        <Text>{product.title}</Text>
        <Text>{product.description}</Text>
      </View>
      <View>
        <TextInput
          keyboardType="numeric"
          value={quantity}
          onChangeText={updateQuantity}
          placeholder="Quantity"
        />
        <TouchableOpacity onPress={addToCart}>
          <Text>Add to Cart</Text>
        </TouchableOpacity>
      </View>
      )}
    </View>
  );

}

Wie du siehst, laden wir die Daten mit der Methode fetchSingleProduct(), die wir in Schritt 2 erstellt haben, und der ID des Produkts, die wir aus dem Routing erhalten. Anschließend können wir die Informationen des Produkts auf unserem Bildschirm anzeigen:

Screenshot des Produktbildschirms

Hinweis: Der Einfachheit halber werden die Produktvarianten hier nicht behandelt. Wenn du Varianten eines Produkts hast (Farbe, Größe...), kannst du diese natürlich auch leicht in der App verwalten. Im Grunde wird alles als Variante in der Shopify-API behandelt. Wenn ein Produkt in deinem Shopify-Panel keine Variante hat, behandelt die API dieses Produkt als ein Produkt mit einer Variante, die die Produktinformationen speichert, wie zum Beispiel den Preis (deshalb bezieht sich unser Code oben auf product.variants[0].price.amount).

Erstellen wir nun den Checkout Bereich

Um einen Warenkorb bearbeiten zu können, musst du zunächst einen Checkout erstellen. Ein Checkout umfasst alles, was für eine Transaktion erforderlich ist (Anzahl der Artikel im Warenkorb, Preise, Steuern, Versandadresse usw.). Es empfiehlt sich, die Checkout-ID in einem persistenten Speicher zu speichern (z. B. mit AsyncStorage oder einem State-Management-Framework wie Redux). Auf diese Weise können wir den Warenkorb des Benutzers leicht abrufen, wenn er die App verlässt und zurückkommt.

Beginnen wir mit dem Hinzufügen einer neuen Funktion in unserer Shopify-Datei:

export async function createCheckout() {
  const checkout = await client.checkout.create();
  return checkout.id;
}

Damit können wir einen Checkout erstellen und die ID in unserem persistenten Speicher aufbewahren. Hier haben wir uns für die Verwendung von Redux entschieden:

import { createCheckout } from '../shopifyFunctions';
const checkoutId = useSelector(selectCheckoutIds);

if (checkoutId === null) {
  const check = await createCheckout();
  dispatch(setId(check));
}

Sobald wir den Checkout für unseren Benutzer erstellt haben, können wir zu unserer Produktkomponente zurückkehren und das Hinzufügen eines Produkts zum Warenkorb ermöglichen.

Ein Produkt in den Warenkorb legen

Zunächst benötigen wir die Shopify-Funktion, um einen Artikel in den Warenkorb zu legen:

export async function addItem(checkoutId, item) {
  return client.checkout.addLineItems(checkoutId, item);
}

In unserer Produktkomponente haben wir bereits den Button, der die Funktion addToCart() aufruft, aber wir müssen die Funktion noch schreiben. Dazu importieren wir die Funktion addItem(), die wir oben erstellt haben, in unsere Komponente. Du benötigst 2 Parameter: die Checkout ID und einen Artikel. Du weißt bereits, dass die checkoutId notwendig ist, um den Einkaufswagen zu identifizieren, dem wir den Artikel hinzufügen wollen. Der Parameter 'item' ist das Produkt selbst. Die Funktion sollte so aussehen:

import { addItem } from '../shopifyFunctions';
const checkoutId = useSelector(selectCheckoutIds);

const addToCart = async () => {
  const item = {
    variantId: product.variants[0].id,
    quantity: parseInt(quantity),
  };
  const ret = await addItem(checkoutId, item);
};

Wie bereits erwähnt, behandelt die Shopify-API Produkte im Warenkorb als Varianten. Unser Artikelobjekt benötigt also die Varianten-ID, um zu wissen, welches Produkt (und/oder welche Variante dieses Produkts, falls vorhanden) wir dem Warenkorb hinzufügen. Dann müssen wir angeben, wie viele davon wir hinzufügen wollen, und das war's! Mit der Varianten-ID ist die API in der Lage, alle benötigten Informationen abzurufen, wie z. B. den Preis. Da wir nun Produkte über unseren Shopify-Checkout in den Warenkorb legen können, erstellen wir eine Warenkorb-Komponente, um alle hinzugefügten Artikel aufzulisten.

Liste der Checkout-Artikel

Wir werden die Cart-Komponente erstellen, um alle Produkte im Checkout aufzulisten.

import { fetchCheckout } from '../shopifyFunctions';

interface Cart {
  id: String;
  items: [{ title: String; id: String; quantity: Number }];
  price: Number;
}

const Cart: FunctionComponent = ({}) => {
  const [cart, setCart] = useState<Cart>();
  const checkoutId = useSelector(selectCheckoutIds);
  const numbers = Array.from({ length: 100 }, (_, i) => i);

  useEffect(() => {
    const fetchData = async () => {
      const data = await fetchCheckout(checkoutId);
      const newCart: Cart = {
        id: data.id,
        items: data.lineItems.map((lineItem: any) => ({
          id: lineItem.id,
          title: lineItem.title,
          quantity: lineItem.quantity,
        })),
        price: data.totalPrice.amount,
      };
      setCart(newCart);
    };
    fetchData();
  }, []);

  return(
    <SafeAreaView>
      <ScrollView>
        <View>
          <Text>Product</Text>
          <Text>Quantity</Text>
        </View>
        {cart?.items.map((lineItem: any) => (
          <View key={lineItem.id}>
            <Text>{lineItem.title}</Text>
            <Picker
              selectedValue={lineItem.quantity}
              onValueChange={(itemValue, itemIndex) => {
                updateQuantity(lineItem.id, itemValue);
              }}
            >
              {numbers.map((number) => (
                <Picker.Item
                  key={number}
                  label={number.toString()}
                  value={number}
                />
              ))}
            </Picker>
          </View>
        ))}
      </ScrollView>
      <View>
        <Text>TOTAL</Text>
        <Text>{cart.price} €</Text>
      </View>
    </SafeAreaView>
  )
}
Bildschirm des Warenkorbs

Alle Produkte, die wir in den Warenkorb gelegt haben, werden hier abgerufen, wobei ihre Menge und der Gesamtpreis automatisch berechnet werden. Wie du sicher bemerkt hast, rufen wir bereits die Funktion updateQuantity() auf, um die Menge der Artikel anzuzeigen. Damit können wir nun die Menge eines Produkts im Checkout ändern.

Aktualisieren von Artikeln im Checkout

Jetzt schreiben wir unsere Funktion wieder zuerst in unsere Shopify-Datei:

export async function updateItem(checkoutId, lineItemToUpdate) {
  return client.checkout.updateLineItems(checkoutId, lineItemToUpdate);
}

Wie du siehst, ist die Update-Funktion ziemlich einfach. Wir identifizieren unseren Checkout, indem wir die ID als Parameter übergeben. Dann geben wir den/die Artikel, die wir aktualisieren wollen, mit den Werten an, die wir aktualisieren wollen. Da wir hier nur die Menge aktualisieren wollen, sieht die Funktion wie folgt aus:

const updateQuantity = async (itemId: String, newQuantity: number) => {
    const item = [
      {
        id: itemId,
        quantity: newQuantity,
      },
    ];
 
    const data = await updateItem(checkoutId, item);

    const updatedCart: Cart = {
      id: data.id,
      items: data.lineItems.map((lineItem: any) => ({
        id: lineItem.id,
        title: lineItem.title,
        quantity: lineItem.quantity,
      })),
      price: data.totalPrice.amount,
    };

    setCart(updatedCart);
  };

In dieser Funktion aktualisieren wir auch unseren lokalen State des Warenkorbs mit den von der Funktion updateItem() zurückgegebenen Artikeln.

Hinweis: Wenn du die Menge auf 0 setzt, wird die Position tatsächlich aus dem Checkout gelöscht. Die Shopify-API verfügt auch über die Funktion removeLineItems(), mit der man den Artikel direkt aus der Kasse löschen kann, indem man einfach die ID übergibt.

Transaktion abschließen

Das ist unser letzter Schritt: Jetzt, wo wir alle Artikel im Warenkorb haben und sie in unserem Checkout gespeichert sind, müssen wir die Transaktion abschließen. Zum Glück kümmert sich Shopify das meiste. Der Checkout (das API-Objekt mit allen Informationen, die wir zum Erstellen der Transaktion benötigen) verfügt nämlich über eine webUrl Eigenschaft. Dabei handelt es sich um eine URL, die alle Checkout-Informationen (Artikel im Warenkorb, Menge usw.) enthält und zum Formular für den Abschluss einer Transaktion weiterleitet:

Shopify-Seite zum Beenden einer Transaktion

Da wir natürlich alles innerhalb unserer Mobile App abwickeln wollen, werden wir diese URL mit Hilfe von React Native Webview in unsere Anwendung integrieren. Dieses Paket ermöglicht es uns, Webinhalte innerhalb unserer Anwendung darzustellen.

Um dies zu tun, musst du die Library installieren, falls du sie nicht bereits hast:

npm install react-native-webview

Jetzt, da wir das Paket haben, wollen wir eine Komponente erstellen, die den Inhalt der Checkout-URL abruft. Bevor wir diese Komponente erstellen, aktualisieren wir den Status unseres Warenkorbs in unserer Cart-Komponente, um die webUrl darin aufzunehmen, damit wir sie einfach als Routenparameter übergeben können, um zu unserer WebView-Komponente zu navigieren.

 const newCart: Cart = {
    id: data.id,
    items: data.lineItems.map((lineItem: any) => ({
      id: lineItem.id,
      title: lineItem.title,
      quantity: lineItem.quantity,
    })),
    price: data.totalPrice.amount,
    checkoutUrl: data.webUrl, // <= add the webUrl to our cart state
  };

Unsere Cart-Komponente enthält bereits einen Bezahl-Button. Damit navigieren wir zur WebView-Komponente:

<TouchableOpacity
  onPress={() => {
    navigation.navigate('Checkout', { uri: cart?.checkoutUrl });
  }}
>
  <Text>Pay</Text>
</TouchableOpacity>

Jetzt erstellen wir die Komponente:

import { WebView } from 'react-native-webview';

const WebViewScreen: FunctionComponent<Props> = ({ route }) => {
  const { uri } = route.params;
  return <WebView source={{ uri }} />;
};

Die WebView kümmert sich nun um alles und ruft den Inhalt in der URL ab, die wir als Parameter übergeben haben.

Shopify-Transaktionsbildschirm

Wie du siehst, wird der Inhalt der URL in unserer App angezeigt. Von dort aus können Nutzer:innen die Transaktion abschließen. Shopify kümmert sich um den Rest!

Dieses Video zeigt alle erstellen Komponenten im Zusammenspiel:

0:00
/1:03

App Demo Video

Mit diesem einfachen Beispiel solltest du in der Lage sein, das Shopify Buy SDK in deiner React Native App zu verwenden. Du kannst natürlich viel mehr tun, wie z.B. eine Versandadresse aktualisieren, einen Rabatt hinzufügen, etc... Schau dir dazu die Dokumentation des Shopify Buy SDK an, um die verschiedenen Funktionen zu sehen, die du in deiner App integrieren kannst.

Denke daran, dass du abhängig von den Aktionen, die du durchführen möchtest, oder den Daten, auf die du in deiner App zugreifen möchtest, diese zuerst in deinem Shopify-Panel autorisieren musst (Schritt 3).

Wenn du Hilfe bei der Erstellung deiner React Native Shopify App benötigst, kontaktiere uns hier!