Du betrachtest gerade Zoho CRM, GitHub und Deluge: Dynamische Angebotsdokumente per HTML-Engine automatisieren

Zoho CRM, GitHub und Deluge: Dynamische Angebotsdokumente per HTML-Engine automatisieren

  • Beitrags-Autor:

Dynamische Dokumente in Zoho: Weg von starren Vorlagen, hin zu einer flexiblen HTML/GitHub-Engine

In der täglichen Arbeit mit CRM-Systemen ist die Erstellung von Dokumenten wie Angeboten, Verträgen oder Rechnungen ein zentraler Prozess. Zoho CRM bietet mit seiner Integration von Zoho Writer ein mächtiges Werkzeug zur Erstellung von Mail-Merge-Vorlagen. Doch was tust Du, wenn Deine Anforderungen wachsen? Wenn Du für verschiedene Länder, Marken oder Geschäftsbereiche hochgradig individualisierte und komplexe Vorlagen benötigst, kann die Pflege dieser Vorlagen schnell zu einer Herausforderung werden. Jede kleine Layout-Anpassung oder rechtliche Änderung erfordert dann die Bearbeitung mehrerer, oft fragiler Dokumente. In diesem Artikel zeigen wir Dir einen alternativen, skalierbaren Ansatz: die Entkopplung Deiner Vorlagenlogik vom CRM durch eine maßgeschneiderte HTML-Template-Engine, die über GitHub verwaltet wird.

Die Herausforderung aus der Praxis: Der Wartungsalbtraum komplexer Vorlagen

Stell Dir ein mittelständisches Unternehmen vor, das seine Produkte und Dienstleistungen in Deutschland und Österreich anbietet. Der Vertriebsprozess sieht vor, dass Angebote direkt aus dem Zoho CRM generiert werden. Die Anforderungen sind jedoch spezifisch:

  • Die Vorlagen für Deutschland und Österreich unterscheiden sich in der Firmierung, den rechtlichen Hinweisen und der Währungssymbolik.
  • Für manche Angebote sollen detaillierte Produktpositionen aufgelistet werden, für andere nur eine Pauschalsumme.
  • Das Corporate Design wird regelmäßig überarbeitet, was Änderungen an Logos, Schriftarten und Farben in allen Vorlagen erfordert.

In der klassischen Zoho-Welt würde dies bedeuten, mindestens vier separate Zoho Writer-Vorlagen zu pflegen: DE mit Positionen, DE ohne Positionen, AT mit Positionen und AT ohne Positionen. Eine kleine Änderung am Footer bedeutet, vier Dokumente zu öffnen, zu bearbeiten und zu hoffen, dass dabei kein Formatierungsfehler entsteht. Dieser Ansatz ist nicht nur zeitaufwendig, sondern auch fehleranfällig und schlecht skalierbar. Was passiert, wenn die Schweiz als dritter Markt hinzukommt?

Schritt-für-Schritt zur flexiblen Angebots-Engine

Wir bauen eine Lösung, die dieses Problem an der Wurzel packt. Anstatt die Vorlagen in Zoho zu verwalten, lagern wir sie als reine HTML-Dateien in ein Git-Repository aus und rufen sie bei Bedarf über eine Custom Function in Zoho CRM ab. Das gibt uns maximale Flexibilität und eine saubere Trennung von Daten (CRM), Logik (Deluge) und Präsentation (HTML/CSS).

Schritt 1: Die Architektur – Warum HTML und GitHub?

Der Kern der Idee ist die Trennung von Design und Daten. HTML und CSS sind der weltweite Standard für die Gestaltung von Inhalten. Ein Git-Repository (wir nutzen hier das Beispiel GitHub) bietet uns entscheidende Vorteile:

  • Versionierung: Jede Änderung an der Vorlage wird nachverfolgt. Ein Fehler gemacht? Mit einem Klick bist Du auf einer früheren, funktionierenden Version.
  • Kollaboration: Webdesigner oder Frontend-Entwickler können an den Vorlagen arbeiten, ohne Zugang zum Zoho-System zu benötigen.
  • Flexibilität: Komplexe Logik, wie das Ein- und Ausblenden ganzer Blöcke, lässt sich mit einfachen Platzhaltern steuern, die unsere Zoho-Funktion später interpretiert.
  • Zukunftssicherheit: Du könntest sogar KI-Tools wie ChatGPT oder Gemini nutzen, um HTML-Strukturen für Deine Vorlagen zu generieren.

Schritt 2: Die intelligente HTML-Vorlage erstellen

Wir legen in unserem GitHub-Repository eine Datei an, z.B. angebot-template.html. Diese Datei enthält das gesamte Layout unseres Angebots. Dynamische Inhalte aus dem CRM werden durch Platzhalter im Format {{modul.feldname}} markiert. Für die Produktpositionen verwenden wir eine Schleife und für länderspezifische Inhalte eine bedingte Anweisung.

<!DOCTYPE html>
<html>
<head>
<style>
  /* Dein CSS für ein ansprechendes Angebot */
  body { font-family: Arial, sans-serif; }
  .header { background-color: #f2f2f2; padding: 20px; }
  .customer-address { margin-top: 30px; }
</style>
</head>
<body>
  <div class="header">
    <h1>Angebot #{{quote.Subject}}</h1>
  </div>

  <div class="customer-address">
    <p>
      {{account.Account_Name}}<br>
      {{contact.Full_Name}}<br>
      {{account.Billing_Street}}<br>
      {{account.Billing_Code}} {{account.Billing_City}}
    </p>
  </div>

  <h3>Unsere Leistungen</h3>
  
  <!-- IF quote.show_line_items == true -->
  <table>
    <tr><th>Produkt</th><th>Preis</th></tr>
    <!-- BEGIN_LOOP product_lines -->
    <tr>
      <td>{{product.Product_Name}}</td>
      <td>{{product.List_Price}}</td>
    </tr>
    <!-- END_LOOP product_lines -->
  </table>
  <!-- ENDIF -->

  <h4>Gesamtsumme: {{quote.Grand_Total}}</h4>

  <!-- IF account.Billing_Country == 'Österreich' -->
  <div class="footer-legal">
    <p>Spezifischer Rechtstext für Österreich...</p>
  </div>
  <!-- ELSE -->
  <div class="footer-legal">
    <p>Standard-Rechtstext für Deutschland...</p>
  </div>
  <!-- ENDIF -->

</body>
</html>

Die speziellen Kommentare wie <!-- IF ... --> und <!-- BEGIN_LOOP ... --> sind unsere eigenen Anweisungen, die wir gleich mit Deluge verarbeiten werden.

Schritt 3: Die Deluge Custom Function im Zoho CRM

Das Herzstück unserer Lösung ist eine Custom Function in Zoho CRM, die wir an einen Button im Angebotsmodul hängen. Diese Funktion führt die folgenden Schritte aus:

  1. Abrufen der HTML-Vorlage von GitHub.
  2. Sammeln aller relevanten Daten aus dem CRM (Angebot, Kunde, Ansprechpartner, Produkte).
  3. Ersetzen der Platzhalter in der HTML-Vorlage mit den CRM-Daten.
  4. Umwandeln des finalen HTML-Codes in ein PDF.
  5. Anhängen des PDFs an den Angebotsdatensatz.

Hier ist ein beispielhaftes Deluge-Skript. Du musst eine Verbindung zu GitHub in Deinem Zoho-Konto einrichten („GitHub_Connector“) und dort Deinen Personal Access Token hinterlegen.

// Argument: quoteId vom Button im Angebotsmodul
// get record details for the quote
quoteDetails = zoho.crm.getRecordById("Quotes", quoteId);
accountId = ifnull(quoteDetails.get("Account_Name"),"").get("id");
contactId = ifnull(quoteDetails.get("Contact_Name"),"").get("id");

// get related data
accountDetails = zoho.crm.getRecordById("Accounts", accountId);
contactDetails = zoho.crm.getRecordById("Contacts", contactId);
productLines = quoteDetails.get("Product_Details");

// 1. Fetch HTML template from GitHub
github_url = "https://raw.githubusercontent.com/DEIN_USER/DEIN_REPO/main/angebot-template.html";
headers = Map();
// Die Verbindung "github_connector" muss in Zoho CRM eingerichtet sein
response = invokeurl
[
	url :github_url
	type :GET
	headers:headers
	connection:"github_connector"
];
htmlTemplate = response.toString();

// 2. & 3. Replace placeholders (simple replacements)
htmlTemplate = htmlTemplate.replace("{{quote.Subject}}", ifnull(quoteDetails.get("Subject"),""));
htmlTemplate = htmlTemplate.replace("{{quote.Grand_Total}}", ifnull(quoteDetails.get("Grand_Total"),""));
htmlTemplate = htmlTemplate.replace("{{account.Account_Name}}", ifnull(accountDetails.get("Account_Name"),""));
// ... weitere einfache Ersetzungen für Account und Kontakt

// Handle conditional blocks
if(ifnull(accountDetails.get("Billing_Country"),"") == "Österreich")
{
	htmlTemplate = htmlTemplate.replaceAll("(?s)<!-- IF account.Billing_Country == 'Österreich' -->(.*?)<!-- ELSE -->(.*?)<!-- ENDIF -->", "$1");
}
else
{
	htmlTemplate = htmlTemplate.replaceAll("(?s)<!-- IF account.Billing_Country == 'Österreich' -->(.*?)<!-- ELSE -->(.*?)<!-- ENDIF -->", "$2");
}

// Handle product loop
// Hier gehen wir davon aus, dass es eine Checkbox im CRM gibt
showItems = ifnull(quoteDetails.get("Show_Line_Items_Checkbox"), false);
if(showItems)
{
    // Entferne die IF-Tags um den Loop
    htmlTemplate = htmlTemplate.replaceAll("(?s)<!-- IF quote.show_line_items == true -->(.*?)<!-- ENDIF -->", "$1");
    
    // Finde den Loop-Block
    loopStart = "<!-- BEGIN_LOOP product_lines -->";
    loopEnd = "<!-- END_LOOP product_lines -->";
    startIndex = htmlTemplate.indexOf(loopStart);
    endIndex = htmlTemplate.indexOf(loopEnd);
    
    if(startIndex > -1 && endIndex > -1)
    {
        loopTemplate = htmlTemplate.substring(startIndex + loopStart.length(), endIndex);
        allProductRows = "";
        for each product in productLines
        {
            productRow = loopTemplate;
            productRow = productRow.replace("{{product.Product_Name}}", product.get("product").get("name"));
            productRow = productRow.replace("{{product.List_Price}}", product.get("list_price"));
            allProductRows = allProductRows + productRow;
        }
        
        // Ersetze den gesamten Loop-Block mit den generierten Zeilen
        fullLoopBlock = htmlTemplate.substring(startIndex, endIndex + loopEnd.length());
        htmlTemplate = htmlTemplate.replace(fullLoopBlock, allProductRows);
    }
}
else
{
    // Entferne den gesamten IF-Block, wenn keine Positionen angezeigt werden sollen
    htmlTemplate = htmlTemplate.replaceAll("(?s)<!-- IF quote.show_line_items == true -->(.*?)<!-- ENDIF -->", "");
}


// 4. & 5. Convert to PDF and attach
// Wir nutzen hier die Zoho Sheet API als "Trick", um aus HTML ein PDF zu erzeugen.
htmlFile = zoho.sheet.createSpreadsheet("temp_quote_file", "html", htmlTemplate);
sheetId = htmlFile.get("resource_id");
// Gib der API einen Moment zum Verarbeiten
response = invokeurl
[
	url :"https://sheet.zoho.com/api/v2/" + sheetId + "?method=export&type=pdf"
	type :GET
	connection:"zohooauth"
];

// Attach the generated PDF to the quote record
uploadResponse = zoho.crm.attachFile("Quotes", quoteId, response);
info uploadResponse;

// Clean up the temporary sheet file
delete_response = zoho.sheet.deleteSpreadsheet(sheetId);
info delete_response;

return "PDF erfolgreich generiert und angehängt.";

Tipps und Best Practices

  • Sicherheit geht vor: Speichere Deinen GitHub Personal Access Token niemals direkt im Code. Nutze immer die gesicherten Verbindungen (Connections) in Zoho, die mit OAuth 2.0 oder API-Keys arbeiten. Für sensible Zugangsdaten ist Zoho Vault die beste Wahl.
  • Fehlerbehandlung: Was passiert, wenn GitHub nicht erreichbar ist? Oder wenn ein Feld im CRM leer ist? Baue Deinen Deluge-Code robust mit try...catch Blöcken und nutze ifnull()-Prüfungen, um unerwartete Fehler abzufangen und dem Anwender eine klare Rückmeldung zu geben.
  • Datenqualität sicherstellen: Diese Automatisierung lebt von sauberen Daten. Mache wichtige Felder wie „Branche“ oder „Land“ im Lead- oder Account-Modul zu Pflichtfeldern. Nutze Picklisten anstelle von Freitextfeldern, um Konsistenz zu gewährleisten. Für die initiale Bereinigung und den Import von Stammdaten ist Zoho DataPrep ein unschätzbares Werkzeug.
  • Den Prozess erweitern: Die Generierung des PDFs ist nur ein Schritt. Integriere den Prozess in einen größeren Workflow. Nach der Erstellung könnte das Dokument automatisch mit Zoho Sign zur digitalen Unterschrift versendet werden. Eine Benachrichtigung über das erstellte Angebot kann an einen Vertriebs-Channel in Zoho Cliq gesendet werden.

Weitere Integrationsmöglichkeiten im Zoho-Ökosystem

Dieser Ansatz lässt sich nahtlos mit anderen Prozessen und externen Datenquellen kombinieren. Bevor ein Angebot erstellt wird, könntest Du beispielsweise die Bonität oder weitere Firmendaten des Kunden über eine API-Anbindung an einen externen Dienst wie den Wirtschafts-Kompass oder eine andere Wirtschaftsauskunftei anreichern. Die so gewonnenen Daten fließen direkt in den Angebotsdatensatz und stehen für die dynamische Generierung Deiner Dokumente zur Verfügung.

Eingehende Leads, die über ein Zoho Forms Formular auf Deiner Webseite erfasst werden, können durch einen intelligenten Zoho Flow laufen, der prüft, ob der Kontakt bereits existiert, ihn dem richtigen Vertriebsmitarbeiter zuweist und erste Daten wie die Branche (z.B. basierend auf MCC-Codes) vorqualifiziert, bevor überhaupt ein Angebot in Frage kommt.

Fazit: Mehr als nur ein Dokumentengenerator

Der Umstieg von starren Zoho Writer-Vorlagen auf eine flexible, via GitHub verwaltete HTML-Engine ist mehr als nur eine technische Spielerei. Es ist ein Paradigmenwechsel, der Dir die volle Kontrolle über Deine geschäftskritischen Dokumente zurückgibt. Du gewinnst an Agilität, reduzierst den Wartungsaufwand drastisch und schaffst eine zukunftssichere, skalierbare Lösung.

Dieser Ansatz zeigt eindrucksvoll, wie die Kombination aus der Low-Code-Power von Zoho (Deluge, Workflow-Automatisierung) und den Best Practices aus der klassischen Softwareentwicklung (Git, Trennung von Code und Design) zu robusten und hochgradig angepassten Unternehmenslösungen führt. Du bist nicht länger auf die Standardfunktionen beschränkt, sondern kannst Dein Zoho-System exakt an Deine einzigartigen Geschäftsprozesse anpassen.


In diesem Lösungsansatz verwendete Zoho Apps: