Nachladen von Google Maps

Dieses HowTo beschreibt eine Lösung für die Pro-Version. Der Besucher erhält durch die Anpassungen die Möglichkeit zu entscheiden, ob Google Maps geladen werden soll.

Hierzu werden die entsprechenden Scripte erst nach Zustimmung des Besuchers geladen und die Entscheidung in einem Cookie gespeichert. An Stelle der Karte wird ein Button angezeigt. Nach einem Klick auf diesen wird ein Datenschutzhinweis mit Link zur Datenschutzerklärung von Google Maps eingeblendet. Der Besucher muss nun durch das Aktivieren einer Checkbox und einem Klick auf den Button "Karte laden" seine Zustimmung bestätigen.

Anschließend wird die Seite mit den entsprechenden Scripten von Google Maps erneut geladen.

Zur Integration sind folgende Schritte notwendig:

  1. Es wird eine Konstante definiert, über die der Integrator diese Funktion aktivieren kann. Hierzu wird folgendes TypoScript für die Konstanten Konfiguration benötigt
# customcategory=tracking=tracking
themes.configuration.tracking {
    # customsubcategory=tracking_googlemap_alert=Google Map Alert
    googleMaps {
        # cat=tracking/tracking_googlemap_alert/10; type=options[0,1]; label= Google Map Alert: Show Button to load Google Maps
        active = 0
    }
}

Um auch im Frontend auf die Einstellung zuzugreifen wird über das folgende Setup TypoScript die Konstante in den Page Settings erreichbar gemacht.

page.10.settings.tracking.googleMaps {
    active = {$themes.configuration.tracking.googleMaps.active}
}

Der Knotenpunkt 10 stellt dabei die Konfiguration Ihres Fluidtemplates dar:

page.10 = FLUIDTEMPLATE
  1. Integrieren des Platzhalters und der Datenschutz-Informationen Hierzu erstellen wir ein neues Partial und erzeugen bzw. erweitern die Sprachdateien für die Texte.

Sprachdatei: typo3conf\ext\my_sitepackage_theme\Resources\Private\Language\locallang.xlf

<?xml version="1.0" encoding="UTF-8" ?>
<xliff version="1.0">
    <file source-language="en" datatype="plaintext" original="messages"
          date="2020-11-16T00:00:00Z" product-name="my_sitepackage_theme">
        <header/>
        <body>
            <trans-unit id="maps_btn_label" xml:space="preserve">
                <source>Karte laden</source>
            </trans-unit>
            <trans-unit id="maps_modal_title" xml:space="preserve">
                <source>Google Map laden</source>
            </trans-unit>
            <trans-unit id="maps_modal_text_heading" xml:space="preserve">
                <source>Datenschutzhinweis</source>
            </trans-unit>
            <trans-unit id="maps_modal_text" xml:space="preserve">
                <source>Wenn Sie die Map  auf dieser Seite sehen möchten, werden personenbezogene Daten an den Betreiber der Map gesendet und ein Cookie durch den Betreiber gesetzt. Daher ist es möglich, dass der Anbieter Ihre Zugriffe speichert und Ihr Verhalten analysieren kann. Die Datenschutzerklärung von Google Maps finden Sie unter: </source>
            </trans-unit>
            <trans-unit id="maps_modal_text_small" xml:space="preserve">
                <source>Bitte beachten Sie, dass nach Ihrer Zustimmung diese Seite neu geladen wird. Formular-Angaben gehen dabei ggf. verloren.</source>
            </trans-unit>
            <trans-unit id="maps_modal_checkbox_label" xml:space="preserve">
                <source>Ich akzeptiere die Datenschutz-Bedingungen und möchte die Map jetzt laden.</source>
            </trans-unit>
            <trans-unit id="maps_modal_btn_label" xml:space="preserve">
                <source>Karte laden</source>
            </trans-unit>
        </body>
    </file>
</xliff>

Fluid Partial: typo3conf\ext\my_sitepackage_theme\Resources\Private\Partials\Elements\GoogleMaps.html

<div xmlns="http://www.w3.org/1999/xhtml" lang="en"
     xmlns:f="http://typo3.org/ns/fluid/ViewHelpers">
    <f:section name="Default">
        <!-- my_sitepackage_theme: Partials/GoogleMaps.html [begin] -->

        <div class="google-maps-alert d-none">
            <div class="map-placeholder">
                <div class="d-flex flex-wrap justify-content-center align-items-center bg bg-light w-100 h-100"
                     style="min-height: 200px;">
                    <button type="button"
                            class="btn btn-primary btn-map-modal"
                            data-toggle="modal"
                            data-target="#google-map-modal"
                            title="{f:translate(key: 'maps_btn_label', extensionName: 'my_sitepackage_theme')}">
                        <f:translate key="maps_btn_label" extensionName="my_sitepackage_theme" />
                    </button>
                </div>
            </div>
        </div>

        <div class="modal" tabindex="-1" role="dialog" id="google-map-modal">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <h4 class="modal-title pl-0">
                            <f:translate key="maps_modal_title" extensionName="my_sitepackage_theme" />
                        </h4>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body">
                        <h3><f:translate key="maps_modal_text_heading" extensionName="my_sitepackage_theme" /></h3>
                        <p>
                            <f:translate key="maps_modal_text" extensionName="my_sitepackage_theme" />
                            <f:link.external uri="https://policies.google.com/privacy"
                                             target="_blank"
                                             title="https://policies.google.com/privacy">
                                https://policies.google.com/privacy
                            </f:link.external>
                        </p>
                        <div class="form-check mb-3">
                            <input class="form-check-input" type="checkbox" value="" id="map-privacy-check">
                            <label class="form-check-label" for="map-privacy-check">
                                <f:translate key="maps_modal_checkbox_label" extensionName="my_sitepackage_theme" />
                            </label>
                        </div>
                        <small>
                            <f:translate key="maps_modal_text_small" extensionName="my_sitepackage_theme" />
                        </small>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-primary btn-load-map" onclick="activateGoogleMaps();">
                            <f:translate key="maps_modal_btn_label" extensionName="my_sitepackage_theme" />
                        </button>
                    </div>
                </div>
            </div>
        </div>

        <!-- my_sitepackage_theme: Partials/GoogleMaps.html [end] -->
    </f:section>
</div>

Damit das Partial geladen wird, muss dieses in einem Seiten Fluid Template oder Partial eingebunden werden, welches auf den Seiten mit der Map genutzt wird. Wir binden den Code meist im Footer Partial ein.

    <f:if condition="{settings.tracking.googleMaps.active}">
        <f:render partial="Elements/GoogleMaps" section="Default"  arguments="{_all}" />
    </f:if>
  1. TypoScript und JS für die Funktionalität

Das folgende JavaScript dient zum setzten und auslesen von Cookies. Datei: typo3conf\ext\my_sitepackage_theme\Resources\Public\JavaScript\Cookies.js

    var Cookies = {
        set: function(name, value, days) {
            var expires = "";
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + (days*24*60*60*1000));
                expires = "; expires=" + date.toUTCString();
            }
            document.cookie = name + "=" + (value || "")  + expires + "; path=/";
        },
        get: function(name) {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');
            for(var i=0;i < ca.length;i++) {
                var c = ca[i];
                while (c.charAt(0) === ' ') c = c.substring(1,c.length);
                if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length,c.length);
            }
            return null;
        }
    };

Das folgende JavaScript dient zum Austauschen der Karten-Ansicht mit dem Platzhalter und dem Merken der Besucher-Entscheidung. Datei: typo3conf\ext\my_sitepackage_theme\Resources\Public\JavaScript\GoogleMapsAllowed.js

    jQuery(document).ready(function () {
        //
        // Google map
        var googleMapsAlert = jQuery('.google-maps-alert').length;
        var googleMapsModal = jQuery('#google-map-modal');
        if (googleMapsAlert) {
            var googleMapsPlaceholder = jQuery('.map-placeholder').html();
            var googleMapsAllowed = Cookies.get('googleMapsAllowed');
            if (googleMapsAllowed === null) {
                var mapWrapperOpenimmoOverview = jQuery('#openimmo-google-map-overview');
                if (mapWrapperOpenimmoOverview.length > 0) {
                    mapWrapperOpenimmoOverview.html(googleMapsPlaceholder);
                }
                var mapWrapperOpenimmo = jQuery('#openimmo-detail-map');
                if (mapWrapperOpenimmo.length > 0) {
                    mapWrapperOpenimmo.html(googleMapsPlaceholder);
                }
                var mapWrapperOpenimmoSearchRequest = jQuery('#openimmo-search-request-map');
                if (mapWrapperOpenimmoSearchRequest.length > 0) {
                    mapWrapperOpenimmoSearchRequest.html(googleMapsPlaceholder);
                    googleMapsModal.find('.close').remove();
                    googleMapsModal.modal({
                        backdrop: 'static'
                    });
                    googleMapsModal.modal('show');
                }
            }
        }
    });

    function activateGoogleMaps() {
        var googleMapsCheckbox = jQuery('#map-privacy-check');
        if (googleMapsCheckbox.is(":checked")) {
            Cookies.set('googleMapsAllowed', '1', 365);
            window.location.reload(false);
        } else {
            googleMapsCheckbox.addClass('is-invalid');
        }
    }

Im folgenden Setup TypoScript wird geprüft, ob die Konstante aktiviert ist und somit der Besucher entscheiden soll, ob die Karte geladen wird.

Sofern die Konstante aktiviert ist werden die beiden oben aufgeführten JavaScript Dateien geladen. Gleichzeitig werden die Scripte zum aufrufen von Google Maps gelöscht.

Wenn der Besucher seine Zustimmung erteilt hat, werden die benötigten Scripte für Maps wieder geladen.

Datei: typo3conf\ext\my_sitepackage_theme\Configuration\TypoScript\Library\googleMapsAllowed.typoscript

#
# Load Google Maps
#
# The google Maps notification / button should to be displayed
# So the visitor has to decide whether to load Google Maps
[{$themes.configuration.tracking.googleMaps.active} == 1]
page {
    includeJSFooterlibs {
        cookie = EXT:my_sitepackage_theme/Resources/Public/JavaScript/Cookies.js
        cookie {
            external = 0
            forceOnTop = 0
            disableCompression = 0
            excludeFromConcatenation = 0
        }
    }

    includeJSFooter {
        googleMapsAllowed = EXT:my_sitepackage_theme/Resources/Public/JavaScript/GoogleMapsAllowed.js
        googleMapsAllowed {
            external = 0
            forceOnTop = 0
            disableCompression = 0
            excludeFromConcatenation = 0
        }
    }
}

# Copy config for scripts to load if user allow Google Maps
lib.googleMapsAllowed.includeJSFooterlibs.googleMaps < page.includeJSFooterlibs.googleMaps
lib.googleMapsAllowed.includeJSFooterlibs.googleMapsHtmlMarker < page.includeJSFooterlibs.googleMapsHtmlMarker
lib.googleMapsAllowed.includeJSFooterlibs.googleMapsClustering < page.includeJSFooterlibs.googleMapsClustering

# Remove scripts form openimmo pro
page.includeJSFooterlibs.googleMaps >
page.includeJSFooterlibs.googleMapsHtmlMarker >
page.includeJSFooterlibs.googleMapsClustering >
[GLOBAL]

# If google Maps loadings is accepted by user
[request.getCookieParams() ['googleMapsAllowed'] == 1]
    page.includeJSFooterlibs.googleMaps < lib.googleMapsAllowed.includeJSFooterlibs.googleMaps
    page.includeJSFooterlibs.googleMapsHtmlMarker < lib.googleMapsAllowed.includeJSFooterlibs.googleMapsHtmlMarker
    page.includeJSFooterlibs.googleMapsClustering < lib.googleMapsAllowed.includeJSFooterlibs.googleMapsClustering
[GLOBAL]