PageSourceSearch

https://www.dgtl.ai/

html dgtl.ai collected 2026-09-24 11:03:41 UTC 10,012 bytes, 243 lines download raw bytes

1<!DOCTYPE html>
2<html mt-scroll-padding>
3<head>
4	
4<script>window.prerenderReady = false;</script>
4
5
6	<base href="/">
7
8	<!--
9		Bootstrap-Daten vorladen. Ohne das ist der kritische Pfad streng serialisiert:
10		das 359-KB-Bundle muss erst geladen UND ausgewertet sein (~855 ms), bevor
11		app.js den ersten API-Request absetzt; localizations und layouts folgen dann
12		nacheinander (~1.253 ms, bis dann gerendert werden kann).
13
14		Hier laufen dieselben Requests ab ~10 ms parallel zum Bundle-Download. Die
15		Antworten landen in window.__preload, gekeyt auf exakt die URL, die Angular
16		spaeter anfragt. app.js liest den Eintrag direkt, localizations und layouts
17		holt der $httpBackend-Decorator in app.preload.js ab.
18
19		Die Sprache wird nicht geraten, sondern aus der configuration-Antwort
20		abgeleitet (gleiche Reihenfolge wie applyConfiguration in app.js), deshalb
21		zwei Wellen statt einer.
22
23		Faellt hier irgendetwas aus (kein fetch, Netzwerkfehler, Exception), bleibt
24		window.__preload leer bzw. der Eintrag verschwindet -- die App laedt dann
25		genau wie vorher. Der Shim darf nie der Grund sein, dass die Seite nicht startet.
26	-->
27	
27<script>
28		(function () {
29			'use strict';
30
31			if (!window.fetch || !window.Promise) { return; }
32
33			var store = window.__preload = {};
34
35			// key = relative URL wie Angular sie anfragt, geladen wird absolut
36			function preload(key) {
37				var pending = fetch('/' + key, { credentials: 'same-origin', headers: { 'Accept': 'application/json' } })
38					.then(function (response) {
39						if (!response.ok) { throw new Error(response.status); }
40						return response.json();
41					});
42
43				pending['catch'](function () { delete store[key]; });
44				store[key] = pending;
45
46				return pending;
47			}
48
49			function resolveLanguage(languages) {
50				var i;
51
52				if (!languages || !languages.length) { return null; }
53
54				function known(code) {
55					for (var j = 0; j < languages.length; j++) {
56						if (code && languages[j].code === code) { return code; }
57					}
58
59					return null;
60				}
61
62				// Zuerst das Sprachsegment der URL: der Root-State ist '/{languageCode}/',
63				// und validateLanguage() in main.controller.js laesst die URL ueber Cookie
64				// und Default gewinnen. Das ist also die Sprache, mit der layouts und
65				// localizations am Ende tatsaechlich geladen werden.
66				var segment = /^\/([^\/?#]+)/.exec(location.pathname);
67				var fromUrl = known(segment ? segment[1] : null);
68
69				if (fromUrl) { return fromUrl; }
70
71				// Danach Cookie, Default, erste Sprache -- wie applyConfiguration() in app.js
72				var cookie = /(?:^|;\s*)_cms_lang=([^;]*)/.exec(document.cookie);
73				var fromCookie = known(cookie ? decodeURIComponent(cookie[1]) : null);
74
75				if (fromCookie) { return fromCookie; }
76
77				for (i = 0; i < languages.length; i++) {
78					if (languages[i].isDefault) { return languages[i].code; }
79				}
80
81				return languages[0].code;
82			}
83
84			// Bisher standen die Font-Hashes fest verdrahtet im <head>, waehrend die
85			// tatsaechliche @font-face-URL zur Laufzeit aus den Styling-Settings gebaut
86			// wird (app.styling.js -> generateFontFace). Zwei Quellen fuer dieselbe URL:
87			// sobald im CMS die Schrift getauscht wird, zeigt der Preload ins Leere.
88			// Jetzt kommt beides aus derselben Quelle -- und der Preload startet bei
89			// ~70 ms statt das @font-face erst nach dem Bootstrap bei ~900 ms zu greifen.
90			function preloadFonts(styling) {
91				if (!styling || !styling.fonts) { return; }
92
93				var roles = ['regular', 'bold', 'headingsRegular', 'headingsBold'];
94				var types = { woff2: 'font/woff2', woff: 'font/woff', ttf: 'font/ttf' };
95				var seen = {};
96
97				for (var i = 0; i < roles.length; i++) {
98					var wrapper = styling.fonts[roles[i]];
99
100					if (!wrapper) { continue; }
101
102					// gleiche Praeferenz wie generateFontFace: der Browser nimmt aus der
103					// src-Liste das erste Format, das er unterstuetzt
104					var format = wrapper.woff2 ? 'woff2' : (wrapper.woff ? 'woff' : (wrapper.ttf ? 'ttf' : null));
105
106					if (!format || !wrapper[format].fileHash) { continue; }
107
108					var href = '/api/static/fonts/' + wrapper[format].fileHash + wrapper[format].extension;
109
110					if (seen[href]) { continue; }
111					seen[href] = true;
112
113					var link = document.createElement('link');
114					link.rel = 'preload';
115					link.as = 'font';
116					link.type = types[format];
117					link.href = href;
118					link.crossOrigin = 'anonymous';
119					document.head.appendChild(link);
120				}
121			}
122
123			try {
124				preload('api/live/configuration').then(function (configuration) {
125					try {
126						preloadFonts(configuration.styling);
127
128						var languageCode = resolveLanguage(configuration.languages);
129
130						if (languageCode) {
131							preload('api/live/localizations/' + languageCode);
132							preload('api/live/layouts/' + languageCode);
133						}
134					}
135					catch (error) { /* App laedt normal weiter */ }
136				}, function () { /* App laedt normal weiter */ });
137			}
138			catch (error) { /* App laedt normal weiter */ }
139		})();
140	</script>
140
141	<title>{{ ngMeta['og:title'] }}</title>
142
143	<meta http-equiv="X-UA-Compatible" content="IE=edge">
144	<meta charset="utf-8" />
145	<meta name="viewport" content="width=device-width, initial-scale=1" />
146	<meta name="robots" content="{{ ngMeta['robots'] }}">
147	<meta name="description" content="{{ ngMeta['description'] }}" />
148	<meta name="keywords" content="{{ ngMeta['keywords'] }}" />
149	<meta name="author" content="dgtl.ai GmbH" />
150	<meta name="geo.region" content="DE-BE" />
151	<meta name="geo.placename" content="Berlin" />
152
153	<!-- Resource Hints für Performance -->
154	<link rel="preconnect" href="https://consent.cookiebot.com" />
155	<link rel="preload" href="libs/css/style-e132c28.css" as="style" onload="this.onload=null;this.rel='stylesheet'" />
156	<noscript><link rel="stylesheet" href="libs/css/style-e132c28.css" /></noscript>
157	<!-- Font-Preloads setzt der Shim oben aus den Styling-Settings, damit sie nicht
158	     mit fest verdrahteten Hashes auseinanderlaufen koennen. -->
159
160	<!-- Open Graph -->
161	<meta property="og:site_name" content="dgtl.ai" />
162	<meta property="og:type" content="{{ ngMeta['og:type'] }}" />
163	<meta property="og:url" content="{{ ngMeta['og:url'] }}" />
164	<meta property="og:locale" content="{{ ngMeta['og:locale'] }}" />
165	<meta property="og:title" content="{{ ngMeta['og:title'] }}" />
166	<meta property="og:description" content="{{ ngMeta['og:description'] }}" />
167	<meta property="og:image" content="{{ ngMeta['og:image'] }}" />
168	<meta property="og:image:width" content="1200" />
169	<meta property="og:image:height" content="630" />
170
171	<!-- Twitter / X Card -->
172	<meta name="twitter:card" content="summary_large_image" />
173	<meta name="twitter:site" content="@dgtlai" />
174	<meta name="twitter:title" content="{{ ngMeta['og:title'] }}" />
175	<meta name="twitter:description" content="{{ ngMeta['description'] }}" />
176	<meta name="twitter:image" content="{{ ngMeta['og:image'] }}" />
177
178	<!-- Canonical & hreflang dynamisch per JS gesetzt (siehe unten) -->
179	<!-- MS / Theme -->
180	<meta name="msapplication-TileColor" content="#ffffff">
181	<meta name="msapplication-TileImage" content="https://www.dgtl.ai/api/live/resources/49c1a410-71e8-c071-d853-0602b3c8fd59.png">
182	<meta name="theme-color" content="#ffffff">
183
184	<link rel="shortcut icon" href="/api/static/favicon/favicon.ico">
185	<link rel="apple-touch-icon" sizes="57x57" href="/api/static/favicon/apple-icon-57x57.png">
186	<link rel="apple-touch-icon" sizes="60x60" href="/api/static/favicon/apple-icon-60x60.png">
187	<link rel="apple-touch-icon" sizes="72x72" href="/api/static/favicon/apple-icon-72x72.png">
188	<link rel="apple-touch-icon" sizes="76x76" href="/api/static/favicon/apple-icon-76x76.png">
189	<link rel="apple-touch-icon" sizes="114x114" href="/api/static/favicon/apple-icon-114x114.png">
190	<link rel="apple-touch-icon" sizes="120x120" href="/api/static/favicon/apple-icon-120x120.png">
191	<link rel="apple-touch-icon" sizes="144x144" href="/api/static/favicon/apple-icon-144x144.png">
192	<link rel="apple-touch-icon" sizes="152x152" href="/api/static/favicon/apple-icon-152x152.png">
193	<link rel="apple-touch-icon" sizes="180x180" href="/api/static/favicon/apple-icon-180x180.png">
194	<link rel="icon" type="image/png" sizes="192x192" href="/api/static/favicon/android-icon-192x192.png">
195	<link rel="icon" type="image/png" sizes="32x32" href="/api/static/favicon/favicon-32x32.png">
196	<link rel="icon" type="image/png" sizes="96x96" href="/api/static/favicon/favicon-96x96.png">
197	<link rel="icon" type="image/png" sizes="16x16" href="/api/static/favicon/favicon-16x16.png">
198	<link rel="manifest" href="/api/static/favicon/manifest.json" crossorigin="use-credentials">
199
200	<link rel="sitemap" type="application/xml" href="/api/live/sitemaps/de/sitemap.xml" />
201	
201<script type="application/ld+json">
202		{
203		  "@context": "https://schema.org",
204		  "@type": "Organization",
205		  "name": "dgtl.ai GmbH",
206		  "url": "https://www.dgtl.ai",
207		  "logo": "https://www.dgtl.ai/api/live/resources/c838e0d8-6fa2-94a4-e67a-385fc6f75973.png",
208		  "contactPoint": {
209			"@type": "ContactPoint",
210			"email": "[email protected]",
211			"contactType": "customer service",
212			"availableLanguage": ["German", "English"]
213		  },
214		  "address": {
215			"@type": "PostalAddress",
216			"streetAddress": "Leipziger Platz 10",
217			"addressLocality": "Berlin",
218			"postalCode": "10117",
219			"addressCountry": "DE"
220		  },
221		  "sameAs": [
222			"https://www.linkedin.com/company/dgtl-ai/"
223		  ]
224		}
225	</script>
225
226	
226<script type="application/ld+json" id="faq-schema"></script>
226
227	
227<script type="application/ld+json" id="breadcrumb-schema"></script>
227
228	
228<script type="application/ld+json" id="webpage-schema"></script>
228
229	
229<script type="application/ld+json" id="article-schema"></script>
229
230
231	<style type="text/css" ng-bind="gcss"></style>
232	<style type="text/css" ng-bind="ccss"></style>
233</head>
234
235<body ng-cloak>
236	<section class="mt-wrapper" ui-view="main"></section>
237	<div cookie-popup-banner config="cookiePopupConfig"></div>
238	
238<script nomodule>
239		var legacyBrowser = true;
240	</script>
240
241	
241<script src="libs/js/app-e132c28.min.js" type="text/javascript" async></script>
241
242</body>
243</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.