# DfCustomCodeManager — Vollständiger Leitfaden

> DfCustomCodeManager liefert eine einfache Antwort auf ein universelles Problem in Shopware-Shops: wohin damit, wie versionieren und wie absichern das benutzerdefinierte CSS und JavaScript, das man immer wieder in einem Theme…

- Seite: <https://www.datafirefly.com/de/documentation/df-custom-code-manager/>
- Sprache: de
- Aktualisiert am: 2026-06-29
- Weitere Sprachen: [fr](https://www.datafirefly.com/documentation/df-custom-code-manager/index.md), [en](https://www.datafirefly.com/en/documentation/df-custom-code-manager/index.md), [es](https://www.datafirefly.com/es/documentation/df-custom-code-manager/index.md), [it](https://www.datafirefly.com/it/documentation/df-custom-code-manager/index.md), [pl](https://www.datafirefly.com/pl/documentation/df-custom-code-manager/index.md), [nl](https://www.datafirefly.com/nl/documentation/df-custom-code-manager/index.md), [pt](https://www.datafirefly.com/pt/documentation/df-custom-code-manager/index.md)
- Index: <https://www.datafirefly.com/de/documentation/llms.txt>

DfCustomCodeManager liefert eine einfache Antwort auf ein universelles Problem in Shopware-Shops: **wohin damit, wie versionieren und wie absichern das benutzerdefinierte CSS und JavaScript**, das man immer wieder in einem Theme ergänzt? Das Plugin bietet einen Code-Editor direkt in der Administration, ein **Container**-System, das **SCSS- oder JavaScript-Snippets** gruppiert, und vor allem eine **direkte Injektion in die Theme-Kompilierung** über Shopwares native Events. Die Konsequenz: keine zusätzliche Datei ausgeliefert, keine zusätzliche HTTP-Anfrage für den Besucher, und Ihre SCSS-Snippets erben automatisch die Variablen und Mixins des aktiven Themes. Diese Anleitung deckt Installation, Konfiguration, das Erstellen von Containern und Snippets, die Theme-Kompilierung, die Versionshistorie, den Safe-Mode, die Vorlagen-Bibliothek, Import/Export und die Fehlerbehebung ab.

## Installation

1. Laden Sie das Archiv `DfCustomCodeManager-1.0.0.zip` aus Ihrem DataFirefly-Konto herunter.
2. Installieren Sie es über **Administration → Erweiterungen → Meine Erweiterungen → Erweiterung hochladen**, oder entpacken Sie den Ordner `DfCustomCodeManager` nach `custom/plugins/`.
3. Führen Sie Installation und Aktivierung durch: ``` bin/console plugin:refresh bin/console plugin:install --activate DfCustomCodeManager bin/console cache:clear ```
4. Bei der Installation erstellt das Plugin seine 4 Tabellen (`df_ccm_container`, `df_ccm_container_sales_channel`, `df_ccm_snippet`, `df_ccm_snippet_version`) und registriert seine Subscriber auf die Theme-Kompilierungs-Events.
5. Kompilieren Sie das Theme neu, damit es das Plugin berücksichtigt: ``` bin/console theme:compile ```

Kompatibel mit Shopware 6.6.x und 6.7.x auf derselben Codebasis (composer `^6.6.0 || ^6.7.0`). Das Administrations-Modul ist **vorkompiliert**, **kein Build erforderlich**. PHP 8.2+ erforderlich. Die SCSS-Kompilierung stützt sich auf `scssphp/scssphp`, das bereits durch `shopware/storefront` mitgeliefert wird. Keine zusätzliche Composer-Abhängigkeit.

## Wo finden Sie das Plugin in der Administration

Nach der Aktivierung erscheint ein **Custom Code Manager**-Eintrag im Menü **Kataloge** der Administration (orangefarbenes Icon, Position 100). Das ist der zentrale Bildschirm: Liste der Container, Suche, Filter und die globalen Aktionen **Importieren**, **Exportieren**, **Vorlagen** und **Theme kompilieren**. Die gesamte Low-Level-Konfiguration (Safe-Mode, Minify, Banner) erfolgt über **Erweiterungen → Meine Erweiterungen → DfCustomCodeManager → ⋯ → Konfigurieren**.

Sollte der Eintrag nach einem Update nicht erscheinen, führen Sie `bin/console assets:install && bin/console cache:clear` aus und laden Sie die Administration mit einem harten Refresh neu (Strg+Shift+R).

## Plugin-Konfiguration

Die Shopware-Plugin-Konfigurationskarte bietet drei einfache, aber wesentliche Schalter:

- **Safe-Mode** (`DfCustomCodeManager.config.safeMode`): standardmäßig deaktiviert. Wenn aktiviert, werden **alle** Container bei der nächsten Kompilierung ignoriert, als wären sie alle inaktiv. Das ist das unten beschriebene Sicherheitsnetz.
- **JS minifizieren** (`DfCustomCodeManager.config.minifyJs`): grundlegende Minifizierung des eingespeisten JavaScripts. Nützlich in Produktion, in Entwicklung deaktiviert lassen, um Snippets im kompilierten Bundle lesen zu können.
- **Banner hinzufügen** (`DfCustomCodeManager.config.addBanner`): fügt einen `/* DataFirefly Custom Code Manager */`-Kommentar am Anfang des eingespeisten Codes ein. Praktisch, um Ihre Snippets im kompilierten Bundle schnell zu finden.

## Das mentale Modell: Container und Snippets

Das Plugin ist auf **zwei Ebenen** organisiert:

- Ein **Container** ist eine logische Gruppierung: _Sommer-Promo 2026_, _GTM-Analytics_, _Dark-Mode-Opt-in_, _CTA-Button-A/B-Test_… Jeder Container hat einen Namen, eine Beschreibung, eine Priorität, einen Aktiv-/Inaktiv-Schalter und einen Geltungsbereich nach Verkaufskanal.
- Ein **Snippet** ist eine Code-Einheit innerhalb eines Containers. Typ SCSS oder JavaScript, Name, Code, Priorität, Aktiv-/Inaktiv-Schalter, Markdown-Notizen und ein Schalter zum Aktivieren oder Deaktivieren der Theme-Variablen-Injektion.

Ein Container kann **mehrere Snippets gemischter Typen** enthalten. Praktisch, um logisch zusammengehörige Snippets zu gruppieren: zum Beispiel ein _Dark-Mode-Opt-in_-Container mit einem SCSS-Snippet für die Styles und einem JavaScript-Snippet für den Klassen-Toggle auf `html`.

## Ihren ersten Container erstellen

1. Klicken Sie unter **Kataloge → Custom Code Manager** oben rechts auf **Neuer Container**.
2. Geben Sie ihm einen aussagekräftigen Namen (z. B. _Sommer-Promo 2026 — Sticky Header & Badge_).
3. Stellen Sie die **Priorität** ein (standardmäßig auf 0 belassen, erhöhen, wenn dieser Container später im Bundle eingespeist werden und damit andere Styles überschreiben soll).
4. (Optional) Aktivieren Sie **Auf bestimmte Verkaufskanäle beschränken** und wählen Sie einen oder mehrere Kanäle. Ist die Option deaktiviert, gilt der Container für **alle** Kanäle.
5. Geben Sie eine Beschreibung ein (interne Notizen, Kontext, zugehöriges Ticket) — sie wird nie ins Bundle eingespeist.
6. Speichern. Sie sind jetzt bereit, Snippets hinzuzufügen.

## Ein SCSS- oder JavaScript-Snippet hinzufügen

In der Karte **Code-Snippets** der Container-Seite gibt es zwei Buttons: **SCSS hinzufügen** und **JavaScript hinzufügen**. Jedes hinzugefügte Snippet erscheint als Karte mit:

- Einem **SCSS**-Badge (info) oder **JS**-Badge (warning).
- Einem Namensfeld (nur im Bearbeitungsmodus sichtbar).
- Einem Aktiv-/Inaktiv-Schalter.
- Einem **Syntax prüfen**-Button (✓).
- Einem **Historie**-Button (Uhr) — ab dem ersten Speichern verfügbar.
- Einem **Duplizieren**-Button.
- Einem **Entfernen**-Button.
- Einem **Code-Editor** mit Syntaxhervorhebung passend zum Typ.
- Einem **Notizen**-Bereich in Markdown, um zu dokumentieren, was das Snippet tut.

Der Code-Editor verwendet nativ die in Shopware 6.7 eingeführte Komponente `mt-code-editor` (basierend auf Meteor). Auf Shopware 6.6 fällt das Plugin automatisch auf `sw-code-editor` zurück (die ältere Ace-basierte Komponente). Als letzter Ausweg (wenn keine Komponente verfügbar ist) übernimmt ein `textarea` in Monospace-Schrift — ohne Syntaxhervorhebung, aber voll funktionsfähig.

## Theme kompilieren

Ein gespeichertes Snippet ist **noch nicht sichtbar** auf der Storefront, solange das Theme nicht neu kompiliert wurde. Zwei Wege:

- Aus der Administration: Button **Theme kompilieren** (oben rechts in der Liste oder auf der Container-Seite). Eine Benachrichtigung bestätigt das Ende der Operation.
- Über die Kommandozeile: ``` bin/console theme:compile ```

Bei der Kompilierung hört das Plugin auf drei Shopware-Events und speist Ihre Snippets dort ein:

- `ThemeCompilerEnrichScssVariablesEvent` — erfasst die SCSS-Variablen-Map des aktiven Themes. Das ist es, was Ihren SCSS-Snippets erlaubt, `$sw-color-brand-primary`, `$font-family-base` usw. zu verwenden.
- `ThemeCompilerConcatenatedStylesEvent` — hängt Ihr kompiliertes SCSS ans Ende des Haupt-Stylesheets an.
- `ThemeCompilerConcatenatedScriptsEvent` — hängt Ihr JavaScript ans Ende des Haupt-Skript-Bundles an.

Ergebnis: **null zusätzliche HTTP-Anfragen** für den Besucher, Ihr Code durchläuft die gesamte Shopware-Optimierungskette (Konkatenation, Minifizierung, Cache-Fingerprinting).

## Vererbung von Theme-Variablen und Mixins

Standardmäßig profitiert jedes SCSS-Snippet von einer **automatischen Präambel**, die alle Variablen und Mixins enthält, die vom aktiven Theme und seinen Theme-Plugins exportiert werden. Sie können in einem Snippet schreiben:

```
.header {
    background: $sw-color-brand-primary;
    font-family: $font-family-base;
    transition: $transition-base;
}
```

…ohne etwas manuell zu importieren, genauso wie in einer Theme-SCSS-Datei. Wenn Sie aus einem bestimmten Grund (Variablenkonflikt, eigenständiges Snippet) diese Vererbung bei einem konkreten Snippet deaktivieren möchten, deaktivieren Sie den Schalter **Theme-Variablen verfügbar** im Footer der Snippet-Karte.

## Multi-Channel-Geltungsbereich

In der Karte **Geltungsbereich & Verkaufskanäle** des Containers aktivieren Sie **Auf bestimmte Verkaufskanäle beschränken** und wählen die relevanten Kanäle aus. Der Container wird dann nur bei Theme-Kompilierungen für diese Kanäle eingespeist. Sehr nützlich für:

- Ein Promo-Banner, das einem sekundären Marken-Shop vorbehalten ist.
- Ein Tracking-Skript, das für einen Markt spezifisch ist.
- Ein A/B-Test auf einem einzelnen Kanal, um den Effekt zu messen.

## Lade-Priorität

Die Priorität ist ein Integer (Standard 0), der die **Injektionsreihenfolge** im kompilierten Bundle steuert: je höher der Wert, desto später wird der Code eingespeist und kann daher mehr überschreiben, was davor kommt. Priorität existiert auf **zwei Ebenen**:

- **Container-Ebene**: Reihenfolge zwischen Containern.
- **Snippet-Ebene**: Reihenfolge zwischen Snippets _innerhalb_ desselben Containers.

Die endgültige Reihenfolge ist: `(Container-Priorität, Snippet-Priorität)` aufsteigend. Einfacher Rat: standardmäßig alles auf 0 belassen, Priorität nur verwenden, wenn Sie wirklich etwas überschreiben müssen.

## Versionshistorie

Bei jedem Speichern eines Snippets erstellt das Plugin automatisch eine **Version** in der Tabelle `df_ccm_snippet_version`. Die **letzten 5 Versionen** pro Snippet werden aufbewahrt (die älteste wird gelöscht, wenn das Limit erreicht ist). Um eine Version zu durchsuchen und wiederherzustellen:

1. Klicken Sie auf der Snippet-Karte auf das **Historie**-Symbol (Uhr).
2. Ein Modal öffnet sich mit der Liste der Versionen: Datum, Autor, Kommentar und Vorschau.
3. Klicken Sie rechts neben der gewünschten Version auf **Wiederherstellen** — der Snippet-Code wird sofort durch den der Version ersetzt. Eine neue Version wird erstellt, um die Wiederherstellung zu protokollieren.
4. Speichern Sie den Container und kompilieren Sie neu, um den Effekt zu sehen.

Für längere Historien bleibt das vollständige Journal in der Tabelle `df_ccm_snippet_version` (alte Versionen werden nur aus dem Modal ausgeblendet). Ein Entwickler kann `VersionTracker::MAX_VERSIONS_PER_SNIPPET` bei Bedarf sehr einfach erweitern.

## Safe-Mode: das Notfall-Sicherheitsnetz

Der Safe-Mode ist ein globaler Schalter in der Plugin-Konfiguration. Wenn aktiviert, sorgt er dafür, dass **jeder Container bei der nächsten Kompilierung ignoriert wird**, ohne dass irgendwelche Daten verändert werden. Typische Verwendung:

1. Ein schlecht getestetes Snippet macht um 22 Uhr etwas in der Produktion kaputt.
2. Gehen Sie zu **Erweiterungen → Meine Erweiterungen → DfCustomCodeManager → ⋯ → Konfigurieren**.
3. Schalten Sie den **Safe-Mode**-Schalter ein und speichern Sie.
4. Kompilieren Sie das Theme neu: `bin/console theme:compile`.
5. Die Storefront ist wieder im nativen Zustand (kein Snippet eingespeist). Sie können das fehlerhafte Snippet jetzt in Ruhe identifizieren und korrigieren.
6. Nach der Korrektur deaktivieren Sie den Safe-Mode und kompilieren erneut.

Der Safe-Mode ist ein Notfall-Werkzeug, kein Betriebsmodus. Sobald der Vorfall behoben ist, denken Sie daran, ihn zu deaktivieren, sonst wird keiner Ihrer Container eingespeist.

## Vorlagen-Bibliothek

Der Button **Vorlagen** (aus der Container-Liste) öffnet eine Bibliothek mit 8 Containern, die mit einem Klick installierbar sind:

- **Sticky-Header** — Header, der sich beim Scrollen verwandelt (Klasse `is-sticky` ab einem Schwellenwert hinzugefügt).
- **Nach-Oben-Button** — Nach-Oben-Button, sichtbar ab einem bestimmten Scroll-Punkt.
- **Cookie-Banner-Skin** — Re-Skinning des nativen Cookie-Banners, um es an Ihre Markenrichtlinien anzupassen.
- **Produkt-Badge — Neu** — "Neu"-Abzeichen auf kürzlich erstellten Produkten.
- **Gratisversand-Leiste** — Gratisversand-Fortschrittsleiste am Seitenanfang.
- **Abgerundete Buttons** — abgerundete Buttons im gesamten Shop.
- **GTM-DOM-Ready-Event** — feuert ein benutzerdefiniertes Event, sobald das DOM bereit ist, um Ihre Data-Layer zu initialisieren.
- **Fade-In beim Scrollen** — progressives Einblenden der Elemente beim Scrollen.

Ein Klick auf **Installieren** erstellt den Container und seine Snippets in der Datenbank. Sie müssen nur noch das Theme neu kompilieren, um sie live zu sehen. Aus Vorlagen erstellte Container sind Container wie jeder andere: Sie können sie bearbeiten, erweitern, deaktivieren, löschen.

## JSON-Import / -Export

Um Snippets zwischen Umgebungen (Dev, Staging, Produktion) oder zwischen Shops zu migrieren:

1. **Export** — wählen Sie einen oder mehrere Container in der Liste aus (Checkboxen), dann klicken Sie auf **Exportieren**. Eine JSON-Datei wird heruntergeladen, die alle ausgewählten Container mit ihren Snippets, ihrer Priorität, ihren Notizen enthält — und die Formatversionsnummer (`EXPORT_VERSION = 1`) zur Rückwärtskompatibilität.
2. **Import** — in der Zielumgebung klicken Sie auf **Importieren** und wählen die JSON-Datei aus. Container und Snippets werden identisch neu erstellt.

Der Import berührt vorhandene Container nicht (keine Zusammenführung über den Namen): Er erstellt immer neue Einträge. Wenn Sie einen vorhandenen Container überschreiben möchten, löschen Sie ihn vor dem Import manuell.

## Syntaxvalidierung

Der ✓-Button **Syntax prüfen** auf jeder Snippet-Karte löst eine serverseitige Validierung aus, ohne etwas zu speichern. Je nach Typ:

- **SCSS** — das Plugin startet eine **Trockenkompilierung** via `scssphp/scssphp` mit der eingespeisten Theme-Variablen-Präambel. Wenn die Kompilierung durchläuft, ist das Snippet gültig. Andernfalls werden die Fehler in einem Fehlerbereich auf der Karte gemeldet (Zeilennummer, Nachricht).
- **JavaScript** — das Plugin bereinigt den Code von Strings und Kommentaren und überprüft dann das **Gleichgewicht der geschweiften Klammern** `{}`, **runden Klammern** `()` und **eckigen Klammern** `[]`. Diese Prüfung ersetzt keinen echten ECMAScript-Parser, fängt aber 90 % der Copy-Paste-Fehler ab (vergessene Klammer, nicht geschlossener String). Für mehr Sicherheit validieren Sie Ihr JavaScript vor dem Einfügen in einem dedizierten Werkzeug.

## Technische Architektur

Für Entwickler, die das Plugin verstehen oder erweitern möchten:

- **Root-PHP-Namespace**: `DataFirefly` (Sub-Namespace: `CustomCodeManager`, Klassen unter `src/`).
- **Plugin-Klasse**: `DfCustomCodeManager` (erweitert `ShopwareCoreFrameworkPlugin`).
- **SystemConfig-Präfix**: `DfCustomCodeManager.config.*`.
- **Tabellen**: `df_ccm_container`, `df_ccm_container_sales_channel`, `df_ccm_snippet`, `df_ccm_snippet_version`.
- **Migrationen**: `Migration1779580800CreateCcmContainerTable`, `Migration1779580801CreateCcmSnippetTable`, `Migration1779580802CreateCcmSnippetVersionTable`.
- **Services**: `CodeCompiler` (Orchestrierung + Cache), `SnippetExporter` (JSON-Import/Export), `SnippetValidator` (Syntaxvalidierung), `VersionTracker` (Snapshot + Restore + Trim).
- **Subscriber**: `ThemeCompilerSubscriber` (die 3 Kompilierungs-Events), `SnippetWrittenSubscriber` (automatischer Snapshot beim Schreiben).
- **Private API-Routen** unter `/api/_action/df-ccm/` (Scope `api`): `validate`, `export`, `import`, `restore-version`, `recompile`, `presets`.

Alle Service-Deklarationen sind in `services.xml` explizit (kein Autowiring), um an den DataFirefly-Konventionen ausgerichtet zu bleiben.

## Erweiterung des Administrations-Moduls

Das Administrations-Modul ist kompiliert und unter `Resources/public/administration/js/df-custom-code-manager.js` abgelegt. Es ist **im ZIP vorkompiliert** und benötigt **keinen lokalen Build**. Um es zu erweitern, finden Sie die Komponenten (`df-ccm-list`, `df-ccm-detail`, `df-ccm-snippet-card`, `df-ccm-code-field`, `df-ccm-preset-modal`, `df-ccm-version-modal`) und passen sie über das Standard-Override-System von Shopware an (`Component.override`).

## FAQ und Fehlerbehebung

**Meine Snippets erscheinen nicht auf der Storefront.** Haben Sie das Theme neu kompiliert? Solange `theme:compile` nach einer Änderung nicht gelaufen ist, ändert sich nichts. Überprüfen Sie auch, ob der Container und das Snippet aktiv sind, ob der relevante Verkaufskanal im Geltungsbereich ist (wenn der Geltungsbereich eingeschränkt ist), und ob der Safe-Mode nicht aktiviert ist.

**SCSS-Kompilierungsfehler in der Konsole nach theme:compile.** Meistens ist es eine Theme-Variable, die nicht existiert (Tippfehler), oder ein SCSS-Snippet, das einen Block öffnet, ohne ihn zu schließen. Deaktivieren Sie das fehlerhafte Snippet, kompilieren Sie neu zur Bestätigung, dann korrigieren Sie in Ruhe. Die Syntaxvalidierung auf der Snippet-Karte fängt die meisten dieser Fälle vor dem Speichern ab.

**Das Custom-Code-Manager-Menü erscheint nicht in der Administration.** Führen Sie `bin/console assets:install && bin/console cache:clear` aus und laden Sie die Administration mit Strg+Shift+R neu. Das Modul befindet sich unter der Gruppe **Kataloge**.

**Der Code-Editor zeigt ein Textarea ohne Syntaxhervorhebung an.** Das ist der Fallback, wenn weder `mt-code-editor` (6.7) noch `sw-code-editor` (6.6) verfügbar ist. Überprüfen Sie Ihre Shopware-Version und ob das Administrations-Modul ordnungsgemäß geladen ist.

**Ich möchte alle Snippets vorübergehend deaktivieren, ohne etwas zu löschen.** Das ist genau der Safe-Mode. Schalter in der Plugin-Konfiguration, Neukompilierung, fertig.

**Der "Theme kompilieren"-Button dreht endlos.** Überprüfen Sie die Shopware-Logs. Die Kompilierung kann bei einem großen Theme dauern; bei einem echten Stillstand liegt die übliche Ursache in einem SCSS-Snippet, das in einer Schleife steckt oder eine unbekannte Variable enthält. Aktivieren Sie den Safe-Mode, kompilieren Sie neu, dann reaktivieren Sie die Snippets einzeln, um den Übeltäter zu identifizieren.

**Mein JavaScript-Snippet wird nicht ausgelöst.** Denken Sie daran, dass der eingespeiste Code **im globalen Bundle** ausgeführt wird, also in einem anderen Kontext als reguläre Shopware-JavaScript-Plugins. Um mit den Storefront-JavaScript-Plugins zu interagieren, hören Sie eher auf `document.addEventListener('DOMContentLoaded', …)` oder die globalen Events, die die Storefront ausgibt.

**Was passiert bei der Deinstallation?** Bei `plugin:uninstall` zeigt Shopware das Standard-Kontrollkästchen **Benutzerdaten beibehalten** an. Wenn es **deaktiviert** ist, löscht das Plugin seine 4 Tabellen und alle zugehörigen Daten (Container, Snippets, Versionen, Kanal-Verknüpfungen). Wenn es **aktiviert** ist, bleiben die Tabellen erhalten und Sie finden Ihre Snippets wieder, wenn Sie das Plugin später neu installieren.
