-
Posts
131 -
Joined
-
Last visited
-
Days Won
25
Mikel last won the day on June 2
Mikel had the most liked content!
About Mikel
- Birthday 06/06/1971
Contact Methods
-
Website URL
https://frameless.at
Profile Information
-
Gender
Male
-
Location
Vienna
-
Interests
my family, design, ux, paragliding, rockclimbing, sailing, mountain biking, skiing, snowboarding
Recent Profile Visitors
Mikel's Achievements
Sr. Member (5/6)
301
Reputation
-
module Stripe Payment Links Admin – Analytics & Reporting
Mikel replied to Mikel's topic in Modules/Plugins
Update: Withdrawals tab + Stripe custom fields (v 1.1.0) Hi all, a quick update on StripePlAdmin, the companion admin module for StripePaymentLinks. Two new things in this release: Withdrawals tab Surfaces the right-of-withdrawal (cancellation) requests that the main module stores per user (spl_withdrawals repeater). Same architecture as the other tabs — configurable columns, status/date/search filters, CSV export — plus inline-editable status and admin notes that save immediately via a small CSRF-protected AJAX endpoint. Consumer name/email link straight to the user account. The tab only shows up when the main module actually provides the feature. Custom Fields column Stripe checkout custom fields (the ones you define on a Payment Link) are now read out of the stored stripe_session meta and shown as Label: Value pairs — text, numeric and dropdown fields (dropdowns mapped back to their option label). It's a configurable column on the Purchases tab, flows into the CSV export, shows up in the purchase-details modal, and is included in the search. As always, feedback welcome, Cheers, Mike- 1 reply
-
- 3
-
-
I couldn't agree with this "love letter" any more than the others already have! When we explored the possibilities of SiteSync, the interplay with RockMigrations and coding agents opened up an incredibly fascinating workflow that we wouldn't want to do without anymore. Our front-end and back-end developers have barely needed to talk to each other since. 😅 Fantastic module, thanks a lot, @bernhard!
-
Hi all — we're putting this one up as a public beta and looking for feedback before we tag a stable release. How it started. Over the past months we've been moving an old blog into a fresh PW site using our own SiteSync module and a Claude Code agent doing most of the migration grunt work. At some point the blog owner mentioned, in that very offhand way clients do, "hey, an image search would be nice." It was Saturday afternoon, so we let the agent build a prototype, pushed it through SiteSync, tested it on the phone an hour later. Worked great. Search results were… not great. But the search wasn't the problem – the underlying data was. Thousands of imported images, almost no descriptions, no tags, no nothing. So we needed a way to retroactively caption and tag a few thousand images without clicking through hundreds of page edits one by one. Since PW (rightly) attaches images to the pages they belong to, we needed a tool that reaches across the whole install at once and – crucially – can edit metadata in bulk. Why not the existing modules? We looked at the two obvious candidates: Media Manager by @kongondo – great if you're starting fresh and want a central media hub. But it's its own storage layer: you upload INTO Media Manager, editors pick FROM Media Manager. Images already sitting on per-page image fields stay invisible to it. Also commercial. MediaLibrary by @BitPoet – adds a MediaLibrary template with its own MediaImages / MediaFiles fields plus a CKEditor picker. Same pattern: a separate page hierarchy you migrate media into. Both are well-designed for "we want a central media model from day one." Neither helps you when the media is already scattered across lead_image, body_images, gallery, images_in_some_repeater etc. Migrating that into a different storage layer would have broken the original page model the blog depends on. So we built Image Library: a Process module that does nothing to your data – it just surfaces a cross-site table view of everything that's already there, with serious bulk editing on top. The bulk-edit part – the reason this module exists. Selection as a paintbrush. You tick N rows across any pages, templates and image fields. Then you edit a cell on ANY of those rows — the popup gains an Add / Replace mode picker (tags additionally offer Remove) and the value gets broadcast to the entire selection in one server round. Same row applies to description, tags, every custom subfield, AND the filename (with placeholders: (n), (n2)..(n5) padded counters, (N) total, (t) page title, (d) date, (p) page name, (f) field name → e.g. rename 200 selected files to event-2025-(n3).jpg). Same row applies to delete (one trash click, whole selection gone behind one confirm dialog with a where-used preflight – see below). Edits that push a row OUT of the active filter ("missing tags" → tag assigned → row no longer matches) fade out and drop from the table; counters auto-decrement. Other highlights: One sortable, paginated, bookmarkable table across every FieldtypeImage field on every page on every template (with config-side blacklists). Inline edit per cell – multilang-aware: language tabs in the popup, all languages committed in one save. Typed widgets per custom subfield: checkbox, date, integer, options (single + multi), and FieldtypePage rendered through PW's actually configured Inputfield (PageAutocomplete / PageListSelect / ASMSelect / whatever the field uses) — no re-implementation. Replace image in place (drag-drop or upload icon) – basename stays, variations regen. Renaming an image in the library instantly rewrites every CKEditor/TinyMCE embed of that file across the site — original and all variations, in every language — so links never break, and a summary dialog shows which pages were updated. Delete with where-used preflight: dialog scans every Textarea via $pages->findIDs("field%='/pid/stem.', include=all") and lists the pages where the image is still embedded in rich text – CKEditor + TinyMCE both, multilang-aware, with direct edit links so you can fix embeds before deleting. JSON / CSV export + import for offline metadata work – hand a CSV to a copywriter or feed it to your agent, get it back, import it. View prefs (columns, page size, bookmarks) live in $user->meta, cross-device. Status. v0.54.x – public beta. Module + docs (EN + DE concept) at GitHub or the Modules Directory Feedback welcome – especially edge cases we haven't seen yet (weird Fieldtype combos in custom-field templates, ProFields, Repeaters / RepeaterMatrix nesting). And if you've got a use case the current feature set doesn't cover, let us know. Cheers, Mike
-
- 12
-
-
-
Hi everyone, a client of ours had a term that shows up all over their site, and they had it registered internationally. So suddenly it needed an ® after every occurrence. The question landed in our inbox as "you probably know an easy way to do this, right?" 😉 There is already Ryan's TextformatterFindReplace, which is powerful and the right tool if you are happy writing regex. We needed something different: a textformatter our clients can edit themselves, i.e. people who do not write regular expressions. So in Annotations you just list the strings and pick options in a small per-string table, no regex anywhere. And so clients never have to touch the Modules section, the module also adds its own page under Setup, guarded by a dedicated annotations-edit permission, where they manage exactly these settings and nothing else. What it can do, for example: Append a mark, the classic case: put (R) (or ©, ™, ...) after a term wherever it appears. Wrap a part of a word, e.g. turn H2O into H2O (subscript the 2). Auto-style certain terms, e.g. make a brand name bold everywhere. Footnote markers, mark only the first occurrence of a term (first-only), great for footnotes1. The real work, though, is in the details that make it safe to hand to an editor: It only changes text, never markup. Tags and their attributes (href, alt, title, class), HTML comments, and the content of skip-tags you configure (code, pre, script, style) are left completely alone. A brand name sitting in a URL or an alt text stays untouched. E-mail addresses are protected. With a frameless to ® rule, info@frameless.at does not turn into info@frameless®.at. It never doubles a mark. It recognises a symbol that is already there, whether it was typed as the literal character (®), as an entity (®, ®, ®, ®, lower or upper case, even with leading zeros), or already wrapped in a tag. No second one gets added. It normalises messy input to your setting. Same spelling, consistent form: a bare symbol gets wrapped, an existing wrapper gets unwrapped (or re-wrapped) if you change the tag later. Editors can be inconsistent and the output still comes out uniform. Longest match wins, and rules compose. Configure both "frameless" and "frameless Media" and each keeps its own treatment. Append runs first, wrap layers on top, so "frameless Media" can be bolded on the word and still get its ® at the end: frameless Media®, while a single "frameless" gets rendered as frameless®. Per-string control: whole-word matching (so cat does not hit category), case sensitivity, and first-occurrence-only, each set per string. Any inline wrap tag: sub, sup, b, strong, em, mark, abbr and more, not just superscript. Get it here https://github.com/frameless-at/TextformatterAnnotations https://processwire.com/modules/textformatter-annotations/ Feedback and ideas welcome. Cheers, Mike!
-
- 6
-
-
-
Hey everyone! Our frontend developer saw GitSync and said "this is lovely for module repos — but what I actually want is the whole /site/ on a branch. Push, switch, done." Reasonable. We said "yeah, we'll get to that." That was a while ago. SiteSync is what we eventually built. What it does: SiteSync deploys a ProcessWire installation's /site/ from a configured GitHub repository — one repo active at a time, but repoint it whenever you like, we're not the boss of you. Every template, stylesheet, RockMigrations config file, content seed lives on a branch. The admin lists every branch in the repo, you click Switch, /site/ is atomically replaced with that branch's tree, RockMigrations applies schema changes on the refresh hook, content seeds run. Click another branch, switch back. Click Rollback on yesterday's deploy, you're on yesterday's deploy. No git binary on the server, no CI runner, no SSH keys — everything goes over the GitHub REST API from PHP. What's new here: Coding-agent fluent. An AI coding agent (Claude Code, Cursor, OpenAI Codex, …) reads a shipped AGENTS.mdfrom your ProcessWire root — which SiteSync auto-scaffolds on install — edits files on a feature branch, opens a draft PR, and the SiteSync admin shows you updates available. We bootstrapped a complete blog — schema, templates, styling, three seed articles — from an iPhone with the Claude app. No laptop in the loop. Real staging via two installs. One SiteSync per environment, both pointed at the same repo, different active branches. Feature → PR onto staging → staging auto-deploys → browse staging.example.com like an actual human → second PR onto live-stable → live deploys. Schema changes hit the staging DB first, not directly into live. The grown-up workflow you usually pay a SaaS for. The technical guts: Versioned everything. Each deploy is <branch> + <SHA> + <commit title> in the Recent deploys table. One-click Rollback to any prior row — the rollback is itself just a regular deploy of that exact tree, same atomic two-pass write, same snapshot, same tracked-sync. Tracked sync, not strict mirror. A new file in your branch shows up on the server. A file your branch never knew about (a third-party module's helper, a hand-edited template, last night's debug log) stays where it is. SiteSync only deletes what SiteSync itself wrote — verified by per-file blob SHA in managed-files.json. Atomic two-pass write. Pass 1 downloads every blob to <final>.sitesync-tmp next to its target. Any failure cleans up all tmp files; /site/ is never half-mutated. Pass 2 POSIX-renames each tmp → final. Pre-deploy snapshots as tar.gz, configurable retention, one-click restore. Your /site/ before SiteSync touches it. If you've ever pasted find . -delete into the wrong shell, this is your safety net. Webhook with hold-back. A direct edit on the server (3am emergency typo fix) is detected; the next webhook push to that same path is held back with HTTP 409 + a clear admin banner instead of silently overwriting your hotfix. The push waits patiently for you to commit and push the local change. Fits your stack: RockMigrations marriage. Fields, templates, roles, permissions as config files under site/RockMigrations/. SiteSync deploys the files and calls $modules->refresh() — RockMigrations hooks the refresh and applies your schema changes. No custom post-deploy step, no extra wiring. Schema-as-code that actually deploys. Editorial seeds under site/content/ for the "first article" / "bootstrap pages" problem — every .php file in there runs on every deploy. The bundled AGENTS.md documents the conventions for keeping seeds safe: idempotency guards (so a re-deploy doesn't duplicate content), and versioned filenames like 99-patch-rename-foo-v1.php for the rare "we need to rename this on every install" case. Conventions, not magic — your seeds are plain PHP doing whatever you want. What it doesn't try to do: replace your CI, sync site/assets/ (uploads stay where the editor uploaded them), or pretend to be a fleet deployer. One site, one active repo, one Switch at a time. The simplicity is the point. Beta status: in active use on real ProcessWire sites. The atomic-deploy + tracked-sync + hold-back + snapshot machinery is stable. The agent-templates and staging walkthrough landed in the most recent sprint and would benefit from more real-world miles. Bugs, edge cases, and "wait, that's a weird hosting setup" reports very welcome. Boring details: License: MIT. Requires: ProcessWire 3.0+, PHP 8.0+ with curl and phar extensions. GitHub token: fine-grained PAT, Contents: read only — read-only. SiteSync literally cannot modify your repo. If the server is ever compromised, the token can pull source code but not push anything back. Get it: Repository: https://github.com/frameless-at/SiteSync Install: drop into /site/modules/SiteSync/, Modules → Refresh → Install README has the whole tour: config, webhooks, path filters, staging walkthrough, agent workflow. Companion to (but not dependent on) GitSync — install both side by side if you want module-level granularity and whole-/site/ branch deploys. SiteSync can even reuse GitSync's GitHub token, because typing the same PAT twice is a crime. One last flex: For a proof of concept we just used SiteSync in combination with Claude to migrate a 20-year-old blog — articles, comments, gallery images, the lot — out of its previous CMS into a fresh ProcessWire install. We just installed the module, pushed /site/ to a Repo and connected the agent to it. We fed it with a JSON Dump of the Blog-Data and said what we wanted: Schema as files on a branch, content as idempotent seeds, snapshots between attempts because of course the image migration didn't work on the first run (or the second, or the third). New /site/ deployed clean, two decades of writing intact, old URLs preserved. Tataaaa. Curious to hear how it lands in your setup. Cheer, Mike
-
- 8
-
-
-
Hi Peter, thanks for taking the time to go through everything in detail – really appreciated. Good to see how much is already done or on the roadmap. Also, I really like your “Nearly Everything at Once” acronym for Neo. 😉 Looking forward to the phased rollout. Cheers, Mike
-
module New Textformatter: Smart Quotes for visible Text
Mikel replied to Mikel's topic in Modules/Plugins
Update: Custom Option – v 1.1.0 A while back, a kind soul forked this module to add Polish quotation marks. Small plot twist: Polish primary quotes are typographically identical to German ones („...“) – so the fork mostly added the word "Polish" to the dropdown. Hats off to the spirit, though. 🇵🇱🇩🇪 Taking the hint, we've now added a Custom option: pick it in the module config and you get two extra text fields where you define your own opening and closing characters. No more forking required when none of the presets fit — Polish, Klingon, or otherwise. 😉 Cheers, Mike -
GitSync – Keep your (private) modules in sync with GitHub
Mikel replied to Mikel's topic in Modules/Plugins
Sorry, @matjazp, that's a genuine data-loss bug on Windows, on us. Root cause: buildLocalFileMap was using SplFileInfo::getPathname() which returns backslash paths on Windows, while the remote tree uses forward slashes. So every subdirectory file looked simultaneously "new" (not in local) AND "deleted" (not in remote) because the key comparison failed. The ZIP path then wrote 980 files and the delete pass immediately removed the same 980 files via their backslash variant — which on NTFS resolves to the same file. That's exactly the "6 files left in root" pattern you saw. Fix is now in branch refactor-install-from-Github: relative paths are normalized to forward slashes in buildLocalFileMap regardless of OS. A few things to double-check before you retry: Sync GitSync branch "refactor-install-from-Github" to latest commit 0f1425e Make sure your manually-restored TracyDebugger matches the upstream master (which it should if you grabbed it from the GH repo directly) Run sync — log should show something like 0 to update, 0 to delete (134 preserved via .gitignore/.gitattributes) and "up to date" If your restore was from git clone rather than the GitHub ZIP, your local will have .gitattributes and docs/ present — those are now matched by the .gitattributes export-ignore filter, so they'll be preserved rather than deleted. Thanks for the precise log output — without the file-count math the Windows-only nature wouldn't have been obvious. Linux/macOS users were unaffected because SplFileInfo::getPathname() already returns forward slashes there. Cheers, Mike -
GitSync – Keep your (private) modules in sync with GitHub
Mikel replied to Mikel's topic in Modules/Plugins
Hi, @maximus, since we do not use OpenAI products (company policy) I haven´t tried Codex at all. But nevertheless, that workflow works — GitSync reacts to any git push, regardless of whether the commit comes from a human, CI, or an agent like Codex Cloud. @matjazp: Thanks for the detailed log — that pinpointed the problem clearly. Three fixes are now in main: PHP execution timeout lifted during sync (set_time_limit(0)). The 500 you hit was almost certainly PHP killing the script at 30–60 s, not GitHub timing out. Large diffs now use the ZIP archive endpoint. When more than 50 files need updating, GitSync fetches a single ZIP of the branch via /zipball/{ref} and copies from the extracted archive instead of hitting /git/blobs/{sha} once per file. Your 1115-file diff turns from ~1115 sequential HTTPS requests into 1 download plus local copies. GitSync now respects two sources at once: .gitignore (which spares Tracy's runtime files like logs/, dumps/, bluescreen/) and .gitattributes export-ignore (which keeps maintainer-excluded files like docs/ and .gitattributes itself off the live install). Both apply bidirectionally — files matching either are never added by the sync and never deleted from local. End result for TracyDebugger: install + first sync = "up to date" with zero unnecessary churn. Please switch to the GitSync branch refactor-install-from-Github in GitSync and give it another try — the log line for the sync should now show N to update, M to delete (P preserved via .gitignore/.gitattributes) – both N and M considerably lower than your original 1115/4430, and you'll also see Using ZIP archive for N file update(s) whenever the update count is above the 50-file threshold. We will merge the branch into main after some internal testing, so feedback is welcome 😉 Cheers, Mike -
GitSync – Keep your (private) modules in sync with GitHub
Mikel replied to Mikel's topic in Modules/Plugins
Hi, @matjazp thanks for the report! We fixed it by removing the 3 calls. Just upgrade the module to 0.2.1 They solve different problems. ProcessWireUpgrade is for stable releases, GitSync is for branch-based development workflows. ProcessWireUpgrade pulls from the official modules.processwire.com directory and compares semantic version numbers. It can upgrade the ProcessWire core itself (master or dev branch) and existing installed modules, but it cannot install new modules that aren't already present, doesn't support private repositories, doesn't support arbitrary branches per module, and uses a pull model (no webhook / no auto-sync on push). Each upgrade is a full download. GitSync pulls from any GitHub repository — public or private (using a fine-grained Personal Access Token for the latter). It works at the branch and commit level rather than the release level, lets you switch any linked module to any branch, and detects changes by comparing git blob SHAs file-by-file, so only modified files are downloaded. It can install brand-new modules from a GitHub URL (even ones not listed in the official directory), supports private repos, and offers GitHub webhook integration for automatic sync on every push. It does not upgrade the ProcessWire core. When to use ProcessWireUpgrade: Production servers that should only move to officially released versions Upgrading the ProcessWire core itself Mostly relying on modules from the official directory When to use GitSync: Test/staging servers that should track a development branch (e.g. develop, feature-x) live Deploying your own modules from private repositories without FTP Installing GitHub-hosted modules that aren't (yet) in the official directory Auto-deploy on every git push via webhook They can be combined: use ProcessWireUpgrade for the core, and GitSync for modules that you develop yourself or that aren´t in the PW directory. To narrow this down — could you share: Which action failed? Install from GitHub, Link Module, or Sync/Upgrade of an already-linked TracyDebugger? The error or behavior you saw — blank page, timeout, rate-limit message, partial sync, etc. The last lines of the gitsync log under Setup > Logs > gitsync. Whether you have a GitHub Personal Access Token configured (without one you're capped at 60 API requests/hour). The file count alone (~1,250) shouldn't be a problem for a normal upgrade — only changed files are downloaded. But it would be a problem for a fresh Install from GitHub, where every file is fetched in its own API call. The log will tell us which case you hit. We just tested and ran into zero problems: We installed Tracy via the Modules page added it to GitSync via the dropdown synced master branch One known gotcha worth checking: TracyDebugger writes runtime files (logs, bluescreens, dumps) into its own module directory. GitSync deletes local files that don't exist in the remote repo, so a large toDelete list with permission-protected files could also cause the upgrade to fail mid-way. Cheers, Mike -
GitSync – Keep your (private) modules in sync with GitHub
Mikel replied to Mikel's topic in Modules/Plugins
Update – Auto-Sync for third party modules – v0.2.0 Hi, folks, a new feature for the GitSync module: for public third-party modules where you can't add a webhook on the source repo, GitSync can now check for upstream updates automatically. How it works Every linked module has a new per-row "Auto-Sync" setting in the GitSync overview: off – manual sync only (default) notify – on the first admin page load per session, GitSync queries GitHub for the tracked branch. If a newer commit exists, a warning notice appears with a direct link to the branches view: auto-sync – same check, but performs the sync immediately without confirmation. Once a remote update has been detected, an orange "update available" badge stays on the GitSync overview next to the affected module – so the info is still there after dismissing the notice. Throttling and scope Checks run once per session (right after admin login), not on every page load. Webhook-active mappings are skipped entirely. GitSync itself is excluded from auto-sync – self-updates remain manual. Why we built it Webhooks are the cleanest path for repos you own. For public modules from other authors you don't control, you'd previously have to remember to check for updates manually. Now the module nudges you on login (or syncs straight away if you trust the upstream). Feedback welcome, Cheers, Mike -
module Native Analytics — a native analytics module for ProcessWire
Mikel replied to Roych's topic in Module/Plugin Development
Thank you very much for adressing this, @Roych! Would it be possible that you release the module either here in the Modules Section and/or on Github? Either way it would simplify the upgrade process of your wonderful module to a one-click action (ProcessUpgrades) or fully automatic (GitSync). Cheers, Mike -
module StripePaymentLinks – Simple Checkout Integration for ProcessWire
Mikel replied to Mikel's topic in Modules/Plugins
StripePaymentLinks 1.2.0 — Electronic withdrawal for B2C distance contracts Hi all, just shipped new version of StripePaymentLinks, which adds a complete electronic right-of-withdrawal flow for online merchants. Why now EU Directive 2023/2673 (amending the Consumer Rights Directive 2011/83/EU) requires every online trader selling to EU consumers — goods, services, or digital products — to provide an easily accessible "withdrawal button" by 19 June 2026. Member states had to transpose the directive into national law by 19 December 2025; Austria's FAGG amendment is one of the implementations now landing. The guiding principle: withdrawing from a contract must not be more burdensome than concluding it. This module ships an electronic withdrawal flow that satisfies that principle, with all legal wording editable per site so it works under any national transposition. What's new Withdrawal modal on every frontend page — Bootstrap 5 modal with form → confirmation → success steps. Renders only when invoked (link or ?withdraw=1 URL parameter); zero overhead otherwise. Per-user withdrawal log — every submission is stored in a repeater on the user template (spl_withdrawals) with timestamp, products affected, salted HMAC-SHA256 IP hash, and a status field that the merchant can update from the backend. Two-mail flow — the customer gets a confirmation of the withdrawal, the merchant gets an internal notification with a direct link to the user profile. Both go through the existing universal mail layout. Order-confirmation mail now includes a consumer-rights block — auto-injected for every purchase, with two outcomes depending on the product: Right of withdrawal applies → withdrawal instructions are rendered. Right has been waived (e.g. immediate digital delivery with explicit consent) → waiver acknowledgement is rendered. Site-editable legal text — two TinyMCE config fields (mailWithdrawalText, mailWaiverText) let each site operator write the exact legal wording their jurisdiction requires. Placeholder system including {products}, {provider}, {contact_email}, {order_id}, {order_date}, {name}, {email}, {today} and — for the TinyMCE editor — anchor-pair placeholders that survive the editor's href-stripping: {withdrawal_mail}TEXT{withdrawal_mail_end} → expands to a prefilled mailto: link (subject + body from translatable defaults) {withdrawal_online}TEXT{withdrawal_online_end} → expands to a ?withdraw=1 deeplink that auto-opens the modal Built-in protection — honeypot field, per-IP rate-limit, server-side CSRF, deliverability headers (Auto-Submitted, X-Auto-Response-Suppress, proper Reply-To). Setup is a few field saves ... In the module config there's a new Withdrawal fieldset with five fields: Internal notification email (falls back to $config->adminEmail) Contact email shown in the form (falls back to sender email) Privacy policy page (page-select) Withdrawal text — right of withdrawal applies (TinyMCE) Waiver text — right of withdrawal does not apply (TinyMCE) The module creates all required fields, the spl_withdrawals repeater and status options on first save / module upgrade — fully idempotent. ... and adding the trigger link to your templates The withdrawal modal is auto-injected on every frontend page — you only need to render a link to open it. The module ships a helper for that: echo $modules->get('StripePaymentLinks')->renderWithdrawalLink(); That gives you the legally required, always-visible withdrawal entry point. Typical place: site footer or account menu. The helper takes two optional arguments — a CSS class and a custom label — so it adapts to whatever markup your theme uses: echo $modules->get('StripePaymentLinks')->renderWithdrawalLink('nav-link fw-bold'); echo $modules->get('StripePaymentLinks')->renderWithdrawalLink('', 'WITHDRAW'); Anything that links to your site root with ?withdraw=1 also auto-opens the modal — useful for putting a direct withdrawal link inside order-confirmation mails, transactional notifications, or PDF receipts. That's the whole frontend integration — one helper call, no JavaScript wiring, no modal HTML in your templates. Translatable All UI strings (modal labels, mail subjects/bodies, status names) are PW-translatable. Happy to hear feedback, edge cases, or implementation experiences from other EU jurisdictions. Cheers, Mike -
module Native Analytics — a native analytics module for ProcessWire
Mikel replied to Roych's topic in Module/Plugin Development
Hi, @Stefanowitsch, I´m curious: Do you hook into a PrivacyWire method or do you use its built in custom function trigger? We simply have set up a script that checks the local storage for the privacywire key. Then a cookie for Native Analytics is set or unset depending on its "statistics" value. Cheers, Mike -
Hi Peter, great to see someone tackling this. SeoMaestro is solidly built and still maintained for bugfixes, but the last feature release was June 2022 and Wanze himself has mentioned he's stepped back from active PW work, if I remember correctly. A few things that come up in client work aren't covered by it alone. I showed your announcement to our SEO specialist and asked him to put together a wishlist. We then discussed it internally and stress-tested every point. What kept coming up wasn't really "we need new features" – it was "the pieces exist, but they don't talk to each other". There's already a lot of good, actively maintained tooling in the ecosystem: Wire Request Blocker (Ryan) – AI bot throttling since September 2025 ProcessRedirects (apeisa / teppokoivula) – 301s, wildcards, CSV import/export, v2.2.5 released Dec 2025 Process404Logger (kixe) – clean 404 logging SeoMaestro (Wanze) – the meta/OG/sitemap foundation everyone already uses The actual pain in daily work is that these live as separate islands. A site owner has to install four modules and configure each one in its own admin section. The obvious workflow between them doesn't exist either – a 404 logged by Process404Logger doesn't surface in ProcessRedirects as a redirect suggestion, even though that's exactly the kind of pairing that would save real time. So the honest question for SEO NEO might not be "what new features do we need" but rather: could SEO NEO act as the umbrella that connects what's already there? A central admin section that surfaces: SEO health (missing descriptions, duplicate titles, noindex flags) as a Lister-based audit view – this genuinely doesn't exist in the ecosystem yet 404 hotspots from the logger with a "create redirect" action wired into ProcessRedirects AI crawler activity from Wire Request Blocker SeoMaestro field status across templates Plus the few things that are genuinely missing on the meta-handling side: Native urlSegments support – as psy mentioned earlier in the thread, currently needs a hook in SeoMaestro Schema.org helpers with documented hooks – ready-made generators for the common types (Article, FAQPage, Person, Organization, BreadcrumbList) that developers can call from templates. Not auto-detection (that doesn't work without explicit mapping), but a clean API. What we deliberately left off the list: llms.txt generator – recent log file audits show GPTBot, ClaudeBot and PerplexityBot don't actually fetch the file. The spec is unofficial and no LLM lab has committed to honoring it. Worth revisiting if that changes. Yoast-style content analysis with traffic-light scoring – tends to produce text optimized for the algorithm rather than the reader. Whether the right path is one big new module or a coordination layer on top of the existing ones is your call. But from the user side, the bigger win would be coherence rather than yet another standalone tool. Looking forward to seeing where this goes. Cheers, Mike