# DfCustomCodeManager: complete gids

> DfCustomCodeManager biedt een eenvoudig antwoord op een universeel probleem van Shopware-shops: waar zet je de eigen CSS en JavaScript die je uiteindelijk toch aan een thema toevoegt, hoe versioneer je…

- Pagina: <https://www.datafirefly.com/nl/documentation/df-custom-code-manager/>
- Taal: nl
- Bijgewerkt op: 2026-08-19
- Andere talen: [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), [de](https://www.datafirefly.com/de/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), [pt](https://www.datafirefly.com/pt/documentation/df-custom-code-manager/index.md)
- Index: <https://www.datafirefly.com/nl/documentation/llms.txt>

DfCustomCodeManager biedt een eenvoudig antwoord op een universeel probleem van Shopware-shops: **waar zet je de eigen CSS en JavaScript die je uiteindelijk toch aan een thema toevoegt, hoe versioneer je die en hoe beveilig je die**? De plugin levert een code-editor die in de administration is geïntegreerd, een systeem van **containers** die **SCSS- of JavaScript-snippets** bundelen, en vooral een **rechtstreekse injectie in de compilatie van het thema** via de native events van Shopware. Het gevolg: geen extra bestand dat wordt geserveerd, geen extra HTTP-aanvraag voor de bezoeker, en uw SCSS-snippets erven automatisch de variabelen en mixins van het actieve thema. Deze gids behandelt de installatie, de configuratie, het aanmaken van containers en snippets, de compilatie van het thema, de versiegeschiedenis, de safe mode, de presetbibliotheek, import en export, en de probleemoplossing.

## Installatie

1. Download het archief `DfCustomCodeManager-1.0.0.zip` vanuit uw DataFirefly-omgeving.
2. Installeer het via **Administration → Extensies → Mijn extensies → Extensie uploaden**, of pak de map `DfCustomCodeManager` uit in `custom/plugins/`.
3. Start de installatie en de activering: ``` bin/console plugin:refresh bin/console plugin:install --activate DfCustomCodeManager bin/console cache:clear ```
4. Bij de installatie maakt de plugin zijn 4 tabellen aan (`df_ccm_container`, `df_ccm_container_sales_channel`, `df_ccm_snippet`, `df_ccm_snippet_version`) en registreert hij zijn subscribers op de events van de themacompilatie.
5. Compileer het thema opnieuw zodat het de plugin meeneemt: ``` bin/console theme:compile ```

Compatibel met Shopware 6.6.x en 6.7.x op dezelfde code (composer `^6.6.0 || ^6.7.0`). De administratiemodule is **vooraf gecompileerd**, er is **geen build nodig**. PHP 8.2+ vereist. De SCSS-compilatie steunt op `scssphp/scssphp`, dat al door `shopware/storefront` wordt geleverd. Geen extra Composer-afhankelijkheden.

## Waar u de plugin vindt in de administration

Na de activering verschijnt er een item **Custom Code Manager** in het menu **Catalogi** van de administration (oranje icoon, positie 100). Dat is het centrale scherm: lijst met containers, zoekfunctie, filters en de globale acties **Importeren**, **Exporteren**, **Presets** en **Thema compileren**. Alle configuratie op laag niveau (safe mode, minify, banner) gebeurt via **Extensies → Mijn extensies → DfCustomCodeManager → ⋯ → Configureren**.

Verschijnt het item na een update niet, voer dan `bin/console assets:install && bin/console cache:clear` uit en herlaad de administration met een geforceerde verversing (Ctrl+Shift+R).

## Configuratie van de plugin

De configuratiekaart van de Shopware-plugin biedt drie eenvoudige maar essentiële schakelaars:

- **Safe mode** (`DfCustomCodeManager.config.safeMode`): standaard uitgeschakeld. Ingeschakeld worden **alle** containers bij de volgende compilatie genegeerd, alsof ze allemaal inactief zijn. Dit is het vangnet dat hieronder wordt beschreven.
- **Minify JS** (`DfCustomCodeManager.config.minifyJs`): basisminificatie van de geïnjecteerde JavaScript. Nuttig in productie, laat het in ontwikkeling uit staan zodat u de snippets in de gecompileerde bundel kunt lezen.
- **Een banner toevoegen** (`DfCustomCodeManager.config.addBanner`): voegt aan het begin van de geïnjecteerde code een commentaar `/* DataFirefly Custom Code Manager */` toe. Handig om uw snippets snel in de gecompileerde bundel terug te vinden.

## Het denkmodel: containers en snippets

De plugin is op **twee niveaus** georganiseerd:

- Een **container** is een logische groepering: _Zomerpromo 2026_, _GTM analytics_, _Dark mode opt-in_, _A/B-test CTA-knop_, enzovoort. Elke container heeft een naam, een beschrijving, een prioriteit, een actief/inactief-schakelaar en een bereik per verkoopkanaal.
- Een **snippet** is een code-eenheid binnen een container. Type SCSS of JavaScript, naam, code, prioriteit, actief/inactief-schakelaar, notities in Markdown, en een schakelaar om het injecteren van de themavariabelen al dan niet te activeren.

Een container kan **meerdere snippets van gemengde types** bevatten. Dat is nuttig om snippets die bij elkaar horen logisch te bundelen: bijvoorbeeld een container _Dark mode opt-in_ met een SCSS-snippet voor de stijlen en een JavaScript-snippet voor de klasseschakelaar op `html`.

## Uw eerste container aanmaken

1. Klik vanuit **Catalogi → Custom Code Manager** rechtsboven op **Nieuwe container**.
2. Geef hem een sprekende naam (bijvoorbeeld _Zomerpromo 2026, sticky header en badge_).
3. Stel de **prioriteit** in (laat 0 als standaard staan, verhoog de waarde als u wilt dat deze container later in de bundel wordt geïnjecteerd en dus andere stijlen overschrijft).
4. (Optioneel) Activeer **Beperken tot verkoopkanalen** en selecteer een of meer kanalen. Staat de optie uit, dan geldt de container voor **alle** kanalen.
5. Vul een beschrijving in (interne notities, context, gekoppeld ticket); die wordt nooit in de bundel geïnjecteerd.
6. Sla op. U kunt nu snippets toevoegen.

## Een SCSS- of JavaScript-snippet toevoegen

Op de kaart **Code-snippets** van de containerpagina staan twee knoppen: **SCSS toevoegen** en **JavaScript toevoegen**. Elk toegevoegd snippet verschijnt als een kaart met:

- Een badge **SCSS** (info) of **JS** (warning).
- Een naamveld (alleen zichtbaar tijdens het bewerken).
- Een actief/inactief-schakelaar.
- Een knop **Syntaxis valideren** (✓).
- Een knop **Geschiedenis** (klok), beschikbaar vanaf de eerste opslag.
- Een knop **Dupliceren**.
- Een knop **Verwijderen**.
- Een **code-editor** met syntaxiskleuring die bij het type past.
- Een zone **Notities** in Markdown om te documenteren wat het snippet doet.

De code-editor gebruikt van nature het component `mt-code-editor` dat in Shopware 6.7 is geïntroduceerd (op basis van Meteor). Op Shopware 6.6 schakelt de plugin automatisch over op `sw-code-editor` (het oude component op basis van Ace). Als laatste redmiddel (component niet beschikbaar) neemt een `textarea` met monospace-lettertype het over, zonder syntaxiskleuring maar volledig bruikbaar.

## Het thema compileren

Een opgeslagen snippet is **nog niet zichtbaar** op de storefront zolang het thema niet opnieuw is gecompileerd. Dat kan op twee manieren:

- Vanuit de administration, met de knop **Thema compileren** (rechtsboven in de lijst of op de containerpagina). Een melding bevestigt het einde van de bewerking.
- Vanaf de commandoregel: ``` bin/console theme:compile ```

Bij de compilatie luistert de plugin naar drie Shopware-events en injecteert daar uw snippets:

- `ThemeCompilerEnrichScssVariablesEvent`: legt de map met SCSS-variabelen van het actieve thema vast. Daardoor kunnen uw SCSS-snippets `$sw-color-brand-primary`, `$font-family-base` en dergelijke gebruiken.
- `ThemeCompilerConcatenatedStylesEvent`: voegt uw gecompileerde SCSS achteraan de hoofdstylesheet toe.
- `ThemeCompilerConcatenatedScriptsEvent`: voegt uw JavaScript achteraan de hoofdscriptbundel toe.

Resultaat: **nul extra HTTP-aanvragen** voor de bezoeker, en uw code doorloopt de volledige optimalisatieketen van Shopware (samenvoeging, minificatie, cachefingerprinting).

## Overerving van variabelen en mixins van het thema

Standaard krijgt elk SCSS-snippet een **automatische preambule** met alle variabelen en mixins die het actieve thema en zijn themaplugins beschikbaar stellen. U kunt dus in een snippet schrijven:

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

zonder handmatig iets te importeren, precies zoals in een SCSS-bestand van het thema. Wilt u om een bepaalde reden (variabeleconflict, zelfstandig snippet) deze overerving voor één specifiek snippet uitschakelen, vink dan de schakelaar **Themavariabelen beschikbaar** in de voettekst van de snippetkaart uit.

## Bereik over meerdere kanalen

Activeer op de kaart **Bereik en kanalen** van de container de optie **Beperken tot verkoopkanalen** en selecteer de betreffende kanalen. De container wordt dan alleen geïnjecteerd in de themacompilaties voor die kanalen. Erg handig voor:

- Een promobanner die alleen voor een tweede merkshop bedoeld is.
- Een trackingscript dat specifiek is voor één markt.
- Een A/B-test op één enkel kanaal om de impact te meten.

## Laadprioriteit

De prioriteit is een geheel getal (standaard 0) dat de **injectievolgorde** in de gecompileerde bundel bepaalt: hoe hoger de waarde, hoe later de code wordt geïnjecteerd en hoe meer die dus kan overschrijven wat eraan voorafgaat. De prioriteit bestaat op **twee niveaus**:

- **Op containerniveau**: de volgorde tussen containers.
- **Op snippetniveau**: de volgorde tussen snippets _binnen_ dezelfde container.

De uiteindelijke volgorde is `(containerprioriteit, snippetprioriteit)` in oplopende volgorde. Eenvoudig advies: laat standaard alles op 0 staan en gebruik de prioriteit alleen als u expliciet iets moet overschrijven.

## Versiegeschiedenis

Bij elke opslag van een snippet maakt de plugin automatisch een **versie** aan in de tabel `df_ccm_snippet_version`. De **laatste 5 versies** per snippet worden bewaard (de oudste wordt verwijderd zodra de drempel is bereikt). Om een versie te raadplegen en te herstellen:

1. Klik op de snippetkaart op het pictogram **Geschiedenis** (klok).
2. Er opent een venster met de lijst met versies, datum, auteur, commentaar en voorbeeld.
3. Klik rechts van de gewenste versie op **Herstellen**; de code van het snippet wordt direct vervangen door die van de versie. Er wordt een nieuwe versie aangemaakt om het herstel vast te leggen.
4. Sla de container op en compileer opnieuw om het effect te zien.

Voor langere geschiedenissen blijft het volledige logboek in de tabel `df_ccm_snippet_version` staan (de oude versies worden alleen in het venster verborgen). Een ontwikkelaar kan `VersionTracker::MAX_VERSIONS_PER_SNIPPET` zo nodig heel eenvoudig verhogen.

## Safe mode: het noodvangnet

De safe mode is een globale schakelaar in de configuratie van de plugin. Ingeschakeld zorgt hij ervoor dat **alle containers bij de volgende compilatie worden genegeerd**, zonder ook maar één gegeven te wijzigen. Typisch gebruik:

1. Een slecht getest snippet breekt om 22 uur iets in productie.
2. Ga naar **Extensies → Mijn extensies → DfCustomCodeManager → ⋯ → Configureren**.
3. Zet de schakelaar **Safe mode** aan en sla op.
4. Compileer het thema opnieuw: `bin/console theme:compile`.
5. De storefront keert terug naar zijn oorspronkelijke staat (zonder enig geïnjecteerd snippet). U kunt nu in alle rust het foutieve snippet opsporen en corrigeren.
6. Zodra het is gecorrigeerd, schakelt u de safe mode uit en compileert u opnieuw.

De safe mode is een noodinstrument, geen gebruiksmodus. Denk eraan hem na het oplossen van het incident weer uit te schakelen, anders wordt geen enkele van uw containers geïnjecteerd.

## Presetbibliotheek

De knop **Presets** (vanuit de containerlijst) opent een bibliotheek met 8 containers die met één klik te installeren zijn:

- **Sticky header**: header die bij het scrollen verandert (klasse `is-sticky` toegevoegd voorbij een drempel).
- **Back to top**: knop terug naar boven, zichtbaar vanaf een bepaalde scrollpositie.
- **Cookie banner skin**: herstyling van de native cookiebanner zodat die bij uw huisstijl past.
- **Productbadge Nieuw**: badge "Nieuw" op recent aangemaakte producten.
- **Free shipping bar**: voortgangsbalk voor gratis verzending bovenaan de pagina.
- **Rounded buttons**: afgeronde knoppen in de hele shop.
- **GTM DOM-ready event**: vuurt een eigen event af zodra de DOM klaar is, om uw data layers te starten.
- **Fade-in on scroll**: elementen verschijnen geleidelijk tijdens het scrollen.

Klikken op **Installeren** maakt de container en zijn snippets in de database aan. Daarna hoeft u alleen nog het thema opnieuw te compileren om ze live te zien. Containers die op basis van een preset zijn aangemaakt, zijn gewone containers: u kunt ze bewerken, uitbreiden, uitschakelen of verwijderen.

## Import en export in JSON

Om snippets tussen omgevingen (dev, staging, productie) of tussen shops te migreren:

1. **Export**: selecteer een of meer containers in de lijst (selectievakjes) en klik daarna op **Exporteren**. Er wordt een JSON-bestand gedownload met alle geselecteerde containers, hun snippets, hun prioriteit en hun notities, plus het versienummer van het formaat (`EXPORT_VERSION = 1`) voor achterwaartse compatibiliteit.
2. **Import**: klik op de doelomgeving op **Importeren** en selecteer het JSON-bestand. De containers en snippets worden identiek opnieuw aangemaakt.

De import raakt bestaande containers niet aan (geen samenvoeging op naam): er worden systematisch nieuwe items aangemaakt. Wilt u een bestaande container overschrijven, verwijder die dan handmatig vóór het importeren.

## Syntaxisvalidatie

De knop ✓ **Syntaxis valideren** op elke snippetkaart start een validatie aan serverzijde zonder iets op te slaan. Afhankelijk van het type:

- **SCSS**: de plugin voert een **proefcompilatie** uit via `scssphp/scssphp` met de preambule van de themavariabelen. Slaagt de compilatie, dan is het snippet geldig. Anders worden de fouten in een foutzone op de kaart getoond (regelnummer, melding).
- **JavaScript**: de plugin ontdoet de code van tekenreeksen en commentaar en controleert daarna de **balans van accolades** `{}`, **haakjes** `()` en **blokhaken** `[]`. Deze controle vervangt geen echte ECMAScript-parser, maar vangt 90 % van de knip-en-plakfouten op (vergeten accolade, slecht afgesloten tekenreeks). Voor meer zekerheid valideert u uw JavaScript in een specifiek hulpmiddel voordat u het plakt.

## Technische architectuur

Voor ontwikkelaars die de plugin willen begrijpen of uitbreiden:

- **PHP-hoofdnamespace**: `DataFirefly` (subnamespace: `CustomCodeManager`, klassen onder `src/`).
- **Pluginklasse**: `DfCustomCodeManager` (breidt `ShopwareCoreFrameworkPlugin` uit).
- **SystemConfig-voorvoegsel**: `DfCustomCodeManager.config.*`.
- **Tabellen**: `df_ccm_container`, `df_ccm_container_sales_channel`, `df_ccm_snippet`, `df_ccm_snippet_version`.
- **Migraties**: `Migration1779580800CreateCcmContainerTable`, `Migration1779580801CreateCcmSnippetTable`, `Migration1779580802CreateCcmSnippetVersionTable`.
- **Services**: `CodeCompiler` (orkestratie en cache), `SnippetExporter` (JSON-import en -export), `SnippetValidator` (syntaxisvalidatie), `VersionTracker` (snapshot, herstel en opschoning).
- **Subscribers**: `ThemeCompilerSubscriber` (de 3 compilatie-events), `SnippetWrittenSubscriber` (automatische snapshot bij schrijven).
- **Private API-routes** onder `/api/_action/df-ccm/` (scope `api`): `validate`, `export`, `import`, `restore-version`, `recompile`, `presets`.

Alle servicedeclaraties staan expliciet in `services.xml` (geen autowiring), in lijn met de conventies van DataFirefly.

## De administratiemodule uitbreiden

De administratiemodule wordt gecompileerd en geplaatst onder `Resources/public/administration/js/df-custom-code-manager.js`. Hij is **vooraf gecompileerd in de ZIP** en vereist **geen lokale build**. Om hem uit te breiden, opent u de componenten (`df-ccm-list`, `df-ccm-detail`, `df-ccm-snippet-card`, `df-ccm-code-field`, `df-ccm-preset-modal`, `df-ccm-version-modal`) en past u ze aan via het standaard override-systeem van Shopware (`Component.override`).

## FAQ en probleemoplossing

**Mijn snippets verschijnen niet op de storefront.** Hebt u het thema opnieuw gecompileerd? Zolang `theme:compile` na een wijziging niet is gedraaid, verandert er niets. Controleer ook of de container en het snippet actief zijn, of het betreffende verkoopkanaal binnen het bereik valt (als het bereik beperkt is), en of de safe mode niet is ingeschakeld.

**SCSS-compilatiefout in de console na theme:compile.** Meestal gaat het om een themavariabele die niet bestaat (typefout) of een SCSS-snippet dat een blok opent zonder het te sluiten. Schakel het verdachte snippet uit, compileer opnieuw ter bevestiging en corrigeer daarna in alle rust. De syntaxisvalidatie op de snippetkaart vangt de meeste van deze gevallen al vóór het opslaan op.

**Het menu Custom Code Manager verschijnt niet in de admin.** Voer `bin/console assets:install && bin/console cache:clear` uit en herlaad de administration met Ctrl+Shift+R. De module zit in de groep **Catalogi**.

**De code-editor toont een textarea zonder kleuring.** Dat is de terugvaloptie wanneer noch `mt-code-editor` (6.7) noch `sw-code-editor` (6.6) beschikbaar is. Controleer uw Shopware-versie en of de administratiemodule daadwerkelijk is geladen.

**Ik wil alle snippets tijdelijk uitschakelen zonder iets te verwijderen.** Daarvoor is de safe mode. Schakelaar in de pluginconfiguratie, opnieuw compileren, klaar.

**De knop "Thema compileren" blijft eindeloos draaien.** Controleer de Shopware-logs. De compilatie kan bij een groot thema tijd kosten; bij een echte blokkade is de gebruikelijke oorzaak een SCSS-snippet dat in een lus loopt of een onbekende variabele bevat. Zet de safe mode aan, compileer opnieuw en activeer daarna de snippets één voor één om de boosdoener te vinden.

**Mijn JavaScript-snippet wordt niet uitgevoerd.** Vergeet niet dat de geïnjecteerde code **in de globale bundel** wordt uitgevoerd, dus in een andere context dan die van de klassieke Shopware-plugins. Om met de JavaScript-plugins van de storefront te communiceren, luistert u beter naar `document.addEventListener('DOMContentLoaded', …)` of naar de globale events die de storefront uitzendt.

**Wat gebeurt er bij het verwijderen?** Bij `plugin:uninstall` toont Shopware het standaard selectievakje **Gebruikersgegevens behouden**. Is het **uitgevinkt**, dan verwijdert de plugin zijn 4 tabellen en alle bijbehorende gegevens (containers, snippets, versies, kanaalkoppelingen). Is het **aangevinkt**, dan blijven de tabellen bestaan en vindt u uw snippets terug als u de plugin later opnieuw installeert.
