IT-Kayali Loyalty
Modular WordPress/WooCommerce loyalty, points and digital stamp card system by IT-Kayali.
by IT-Kayali · github.com/it-kayali/alowidat-loyalty-plugin · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/it-kayali/alowidat-loyalty-plugin/archive/refs/heads/main.zipCurrent version: 0.3.1
IT-Kayali Loyalty is a modular WordPress loyalty foundation for Alowidat. The long-term goal is one central loyalty account per customer across the website, optional WooCommerce and the physical shop. WooCommerce remains optional so the loyalty core can operate independently.
Phase 3 status
Version 0.3.1 keeps the normal WooCommerce My Account login page and the standalone Treuekonto login/registration page side by side. Loyalty-only customers now set a real password while confirming their email, so the same account can sign in through either login page; Magic-Link emails also provide a secure password setup/change link.
Implemented:
- installable WordPress plugin bootstrap and
ITKayali\Loyaltynamespace - schema-versioned database migrations
- dedicated tables for members, cards, WordPress links, ledger, redemptions, reservations, external references, branches and one-time account tokens
- independent
member_uuid; loyalty identity is not based on the WordPress/WooCommerce user ID - roles
itk_loyalty_customeranditk_loyalty_staff - frontend-only access protection for loyalty customers/staff; no normal wp-admin access and no admin bar
- WooCommerce My Account is the central logged-in account shell when WooCommerce is active; loyalty-only customers see only Treuekonto and Abmelden
- loyalty-only customers are redirected from all other WooCommerce account endpoints to
/my-account/treuekonto/ - existing WooCommerce customers receive Treuekonto as an additional menu entry and can explicitly activate loyalty there
- loyalty-only customers can explicitly upgrade the same WordPress user to the WooCommerce
customerrole; the loyalty member is not recreated - upgraded customers keep the normal WooCommerce menu plus Treuekonto
- automatically created Treuekonto page with
[itk_loyalty_account] - customer registration with only name and email
- duplicate protection against an existing loyalty email and against silently enrolling an existing WordPress/WooCommerce account
- email verification with hashed, one-time, expiring tokens
- verification-link resend flow
- shared frontend password login for existing WordPress users
- Magic Link login for active loyalty customers
- generic Magic-Link responses to reduce email-account enumeration
- rate limiting for registration, login-link and email-change requests
- customer account view with current ledger-derived point balance
- profile update for name and email
- email changes remain pending until the new address is verified; the old address remains valid until then
- database-level uniqueness protection for pending email changes and rollback protection when the linked WordPress email cannot be finalized
- optional integration contract so WooCommerce and helloCash can be added later as adapters
- non-destructive deactivation/uninstall behavior by default
Not implemented yet: digital cards, QR generation, stamps, staff scanner, reward redemption, automatic WooCommerce point earning/reversals and helloCash.
Requirements
- WordPress 6.4 or newer
- PHP 8.1 or newer
- MySQL/MariaDB supported by the installed WordPress version
- HTTPS is strongly recommed and will be mandatory for camera scanning in a later phase
- WordPress email delivery must be configured for verification and Magic Links
- WooCommerce is not required for the plugin core
Installation / upgrade
- Upload
it-kayali-loyalty.zipin WordPress → Plugins → Add New → Upload Plugin. - If version 0.1.0 is already installed, replace the existing plugin with the ZIP when WordPress asks.
- Keep the plugin active.
- Version 0.3.1 reuses schema version 2, creates/reuses the standalone Treuekonto page, registers the WooCommerce
/my-account/treuekonto/endpoint, keeps the native WooCommerce login page, and enables explicit account linking when WooCommerce is active. - Open the Treuekonto page and test registration with an email address that is not already used by a WordPress user.
Shortcodes
[itk_loyalty_account]
Primary unified customer page. Logged-out visitors see:
- password login for existing WordPress users
- Magic Link request for active loyalty customers
- verification-link resend
- loyalty registration with name + email
Logged-in loyalty customers see their loyalty account/profile and current ledger-derived point balance.
[itk_loyalty_login]
Optional standalone rendering of the same login/Magic-Link forms. Normally [itk_loyalty_account] is preferred to keep the customer journey unified.
[itk_loyalty_register]
Optional standalone registration form. Normally [itk_loyalty_account] is preferred.
Roles
Loyalty Customer
Internal role key: itk_loyalty_customer
This role is created for loyalty-only customers. A random bootstrap password is generated internally at account creation and is never shown. During email confirmation the customer must set a personal password. After that the same account can sign in through both the standalone Treuekonto login and the normal WooCommerce My Account login; Magic Link remains available as an additional passwordless option. Customers have no normal wp-admin access and no admin bar.
Loyalty Staff
Internal role key: itk_loyalty_staff
Phase 1/2 grants only the minimal loyalty capabilities required by the later staff workflow:
readitk_loyalty_scan_membersitk_loyalty_add_pointsitk_loyalty_redeem_rewards
The actual staff frontend is Phase 6.
Customer flow in 0.3.1
- Customer opens the standalone Treuekonto page.
- New loyalty-only customer enters name + email.
- The system creates an independent loyalty member, a restricted WordPress user link and a one-time verification token.
- The verification email opens E-Mail bestätigen & Passwort festlegen.
- The customer chooses a personal password; only then is the email confirmed, the loyalty member activated and the customer signed in.
- The same loyalty account can thereafter sign in with email + password on either
/treuekonto/or the normal WooCommerce/my-account/login page. - Magic Link remains available. Its email also contains a separate one-time password setup/change link, which gives existing pre-0.3.1 loyalty accounts a migration path to a known password.
- When WooCommerce is active, the logged-in loyalty-only customer lands in
/my-account/treuekonto/. - Loyalty-only customers see only Treuekonto and Abmelden in the account menu.
- Name can be changed immediately.
- A new email address is stored only as pending until the new mailbox confirms it. The old email remains authoritative meanwhile.
Existing WordPress/WooCommerce users are deliberately not silently enrolled during loyalty registration.
Existing WooCommerce customer → Loyalty
- The customer logs into the existing WooCommerce account.
- Treuekonto is available in My Account.
- The customer explicitly chooses Treueprogramm aktivieren.
- The plugin reuses the same WordPress/WooCommerce user and creates only the independent loyalty member/link.
- A verification email is sent to the shop-account email.
- After confirmation, loyalty becomes active and the customer keeps the full WooCommerce menu plus Treuekonto.
Loyalty-only customer → WooCommerce shop account
- The verified loyalty customer opens Treuekonto.
- The customer explicitly chooses Auf Shop-Konto upgraden.
- The existing WordPress user receives the WooCommerce
customerrole. - No new loyalty member is created:
member_uuid, ledger, balance and history remain unchanged. - The normal WooCommerce account areas become visible in addition to Treuekonto.
Database foundation
The plugin uses the active WordPress table prefix and creates:
{prefix}itk_loyalty_members{prefix}itk_loyalty_cards{prefix}itk_loyalty_user_links{prefix}itk_loyalty_ledger{prefix}itk_loyalty_redemptions{prefix}itk_loyalty_reservations{prefix}itk_loyalty_external_refs{prefix}itk_loyalty_branches{prefix}itk_loyalty_tokens
Version 0.2.0 adds pending-email fields to the member schema and the token table. Only SHA-256 hashes of verification/Magic tokens are persisted; raw login tokens are never stored in the database.
The point balance is derived from ledger movements rather than maintained as a silently editable independent number.
Security foundation
Current protections include:
- WordPress nonces for state-changing frontend forms
- server-side input validation and sanitization
- output escaping
- WordPress prepared queries for lookups
- dedicated capabilities and restricted roles
- wp-admin blocking for loyalty customer/staff roles
- verification-only account state for pending loyalty customers; unverified accounts cannot use the active loyalty dashboard
- admin-bar hiding for restricted loyalty roles
- random one-time verification/Magic tokens stored only as hashes
- separate one-time password-setup tokens stored only as SHA-256 hashes; password links expire after 60 minutes
- token expiry and one-time consumption
- rate limiting for public email-triggering actions
- generic Magic-Link/resend responses to reduce account enumeration
- duplicate loyalty-email protection
- WooCommerce account-email guard for linked loyalty customers; verified email changes remain centralized in Treuekonto
- no customer data in any QR because QR functionality is not implemented yet
Later points/redemption endpoints will additionally require transactional locking, idempotency and concurrency controls.
Points and rewards rules
These business rules remain planned but are not active in version 0.3.1:
- eligible 50 ml perfume: 1 point per purchased unit
- eligible 100 ml perfume: 1 point per purchased unit
- other sizes: no points
- 10 points: one eligible 50 ml designer-perfume reward
- points remain in the ledger until an actual redemption subtracts 10 points
- no automatic expiry in the first functional release
Known limitations
- email delivery depends on the WordPress mail configuration; production should use a reliable SMTP/provider setup
- WooCommerce opt-in/account upgrade is implemented, but automatic point earning from WooCommerce orders is not yet active
- no digital card, stamps or QR code yet
- no admin dashboard yet
- no staff frontend/scanner yet
- no points earning/redemption service yet
- no helloCash integration yet
- the automatically created Treuekonto page intentionally uses the shortcode and the active theme's surrounding layout
Roadmap
- 0.1.x / Phase 1: project foundation
- 0.2.0–0.2.2 / Phase 2: loyalty-only customer registration, verification, shared login/Magic Link, account data and WooCommerce My Account integration
- 0.3.0–0.3.1 / Phase 3: WooCommerce explicit opt-in/linking, loyalty-to-shop upgrade, dual login pages and verified password setup without changing
member_uuid, points or history - Phase 4: digital card, 10-stamp progress, full-card count and private QR identity
- Phase 5: WordPress administration
- Phase 6: frontend staff workflow and scanner
- Phase 7: WooCommerce earning, reversals and online reward reservations
- Phase 8: security/concurrency/duplicate/performance hardening and acceptance tests
- Phase 9: helloCash adapter after API capability review
Versioning
GitHub Actions validates PHP syntax and version consistency on every push/PR, builds the installable ZIP, and on a successful push to main creates the matching vX.Y.Z Git tag/GitHub Release when it does not already exist. The release asset is built from the same commit and excludes repository-only files such as .github, .gitignore and .gitkeep.
The project follows SemVer-oriented releases. Plugin header, runtime constant, README/readme and packaged ZIP must represent the same version.
See CHANGELOG.md for release history.