chatixy / contao-chatixy
Chatixy AI support agent for Contao - paste your widget key, no code.
Package info
github.com/Devoflex/contao-chatixy
Type:contao-bundle
pkg:composer/chatixy/contao-chatixy
Requires
- php: ^8.1
- contao/core-bundle: ^4.13 || ^5.0
- symfony/config: ^5.4 || ^6.0 || ^7.0
- symfony/dependency-injection: ^5.4 || ^6.0 || ^7.0
- symfony/http-kernel: ^5.4 || ^6.0 || ^7.0
Requires (Dev)
- contao/manager-plugin: ^2.0
Suggests
None
Provides
None
Conflicts
- contao/core: *
- contao/manager-plugin: <2.0 || >=3.0
Replaces
None
README
Adds the Chatixy AI support agent to every front end page of a Contao site. Install it, paste your widget key, tick one checkbox. No template edit, no layout change, no insert tag to place - and it works the same on a classic PHP layout and on a Contao 5 Twig-slot layout.
Requirements
| Contao | 4.13 or 5.x (contao/core-bundle: ^4.13 || ^5.0) |
| PHP | 8.1+ |
| Symfony | 5.4, 6.x or 7.x |
| Licence | MIT |
The package is a contao-bundle and ships a Contao Manager Plugin, so the
Managed Edition registers the bundle for you - there is no kernel file to edit.
Install
composer require chatixy/contao-chatixy vendor/bin/contao-console cache:clear
Or install it from the Contao Manager, which clears the cache for you.
Then go to Back end -> System -> Settings -> Chatixy AI Support Agent. Tick Show support agent, paste your Widget key, and save. The checkbox is off until you tick it, so installing the bundle never changes a live site on its own.
The key field accepts any of the three shapes the dashboard hands out:
- the bare 64-character key,
<key>.js,- the whole
<script src="https://chatixy.com/source/<key>.js" async></script>snippet.
The key is extracted from whatever you paste - the first 64-character hex run wins - and only the bare key is stored. Leave it empty and the bundle does nothing at all.
Both settings are site-wide: they extend Contao's own tl_settings (the
DC_File container that persists to system/config/localconfig.php), rather
than adding a table and a back end module for two scalars. Contao caches DCA
definitions, so clear the cache after installing.
No Chatixy account yet? Start at https://chatixy.com/register.
What it does
On every front end page it splices one tag in before the closing </body>:
<script src="https://chatixy.com/source/<key>.js?platform=contao" async data-chatixy-source="contao"></script>
That is the whole payload. Nothing is added to <head>, no CSS, no extra
requests from the server side.
The hook it uses, and why
The listener runs on modifyFrontendPage, registered with the
#[AsHook('modifyFrontendPage')] attribute. That hook receives the finished
HTML of the page as a string, after insert tags have been replaced, whatever
produced it - so the bundle is independent of your theme, your templates and
your layout type.
The obvious alternative, generatePage with $GLOBALS['TL_BODY'], is
deliberately not used: it only fires from PageRegular, the classic
PHP-template page controller. Contao 5's Twig layout with slots does not render
through that controller, so on such a site the support agent would silently
never appear - a failure mode that is invisible while you develop against a classic
layout and only shows up on the customer's modern theme.
Where it does not inject
- Anything with no
</body>. An XML feed, a JSON response rendered through a front end template, or a partial is returned byte-for-byte untouched. - A page that already carries the loader. The
data-chatixy-sourceattribute doubles as the marker the listener greps for, so a page assembled from more than one front end template still gets exactly one tag rather than a double-booted support agent. - Anything, when the stored key is not a real 64-character hex key. The key
is re-sanitised on read rather than trusted, so a value written straight into
localconfig.phpby a CLI script cannot produce a loader tag either.
The tag goes before the last </body> in the buffer, because a page may
legitimately contain that literal string earlier - a code example, an escaped
snippet in a news article - and the real document end is the last one.
Security: the origin is pinned
The widget key is public; the host is not configurable. There is
deliberately no "advanced host" field, no container parameter and no environment
variable, because a stored host would build a first-party <script src> on
every front end page - i.e. site-wide stored XSS if it could ever be influenced.
A back end form can be CSRF'd and localconfig.php can be written by other
means, so stored settings are not treated as a trust boundary here.
Chatixy\ContaoBundle\Service\ChatixyKey::sanitizeHost() accepts only an
https origin whose host is chatixy.com or a subdomain of it, and returns
the canonical https://chatixy.com for anything else. The pattern is anchored
at both ends and only ever grows the host to the left of a literal dot, so
evilchatixy.com, chatixy.com.evil.example, chatixy.com@evil.example and
http://chatixy.com are all rejected. The emitted src is HTML-escaped at the
point of output as well, even though every component of it is already
constrained to hex characters and a pinned origin.
Support
- Docs and account: https://chatixy.com
- Help: https://chatixy.com/support
- Email: support@chatixy.com
MIT licensed. See LICENSE.