Salesforce Connector for jCustomer
Bidirectional synchronization between Salesforce and Apache Unomi (jCustomer) profiles, configured entirely from a jContent admin panel — no code.
Keep your CDP and your CRM in step. This module links Salesforce and jExperience's jCustomer (Unomi) profiles in both directions, with a visual field-mapping UI, flexible scheduling, and enterprise-grade security. Authentication uses the Salesforce JWT Bearer OAuth 2.0 flow (RS256) — no client secret, and the private key never leaves your server.
Inbound — Salesforce → jCustomer
- Pull Contact, Account, and Lead data into jCustomer profile properties.
- Triggers: scheduled batch (delta by last-modified date), on user login, or manual "Sync now".
- Records are matched to profiles by a stored Salesforce id, else by email.
Outbound — jCustomer → Salesforce
- Push jCustomer profiles to a Salesforce Lead or Contact (you pick the target).
- Poll-based, following the approach of Jahia's official Workato Unomi connector — no plugin deployed into jCustomer, nothing to install container-side.
- Fires on profile updates (email required) and form submissions; matched records are updated, unmatched profiles create a new one, and the new id is written back for idempotent future syncs.
- Friendly schedule builder (every N minutes, hourly, daily, weekly, monthly) or on-demand.
Admin & operations
- Configuration UI under jContent → Administration: connection, field mapping per object, triggers, and sync state.
- Export any object's field mapping to CSV or JSON, in either direction, for documentation or migration.
- Configuration is stored in the JCR under typed node types — fully browsable in the Definitions / JCR browser.
Security built in
- Admin actions restricted to server or site administrators.
- Same-origin (CSRF) defense on every action.
- SSRF allow-list on the Salesforce instance URL; SOQL escaping on user-derived values.
- No secrets in source; the RSA private key is stored in the JCR and never returned to the browser.
Requirements: Jahia 8.2, jExperience, and a reachable jCustomer / Unomi service; a Salesforce Connected App configured for the JWT Bearer flow.
Screenshots
How to install
1. Install the module
- From the Jahia Store: click Install on this listing, or
- Manually: download jcustomer-sfdc-connector-2.2.0.jar and deploy it via the jContent Module Manager, the Provisioning API, or your instance's hot-deploy folder (/var/jahia/modules/).
2. Enable it on your site (Administration → Modules), and make sure jExperience and a jCustomer / Unomi service are available.
3. Create a Salesforce Connected App for the JWT Bearer flow:
- Enable "Use digital signatures" and upload your public certificate.
- OAuth scopes including api; pre-authorize the running user.
4. Configure runtime settings (OSGi config org.jahia.community.jcustomer.sfdc.cfg): set jcustomer.site.key to your jExperience site key, and the jCustomer URL/credentials for your environment (use the container hostname, e.g. http://jcustomer:8181, not localhost).
5. Open the admin panel — jContent → Administration → Sync Salesforce ⇄ jCustomer:
- Connection: enter the Connected App credentials + PEM private key, then Test connection.
- Field Mapping: map fields per object for each direction.
- Triggers: enable inbound (schedule / on-login) and outbound (target object, profile-update / form-submission, schedule), or run Sync now.
Upgrading from an earlier version: deploy the 2.2.0 jar, then run the one-time migration patch migration/2100-migrate-config-to-typed.groovy once (drop it into <jahia>/patches/groovy/) to convert existing configuration to the typed JCR layout. New installs need no migration.
FAQ
Do I need to install anything inside the jCustomer / Unomi container?
No. Outbound sync is poll-based and runs entirely from the Jahia module — no Unomi plugin, no webhook, nothing deployed container-side.
Which Salesforce objects are supported?
Inbound: Contact, Account, and Lead. Outbound: a single chosen target — Lead or Contact.
How does authentication work? Do I need to store a client secret?
It uses the Salesforce JWT Bearer OAuth 2.0 flow (RS256). There's no client secret; you upload a certificate to the Connected App and store the matching RSA private key in Jahia, where it stays server-side.
How are profiles and Salesforce records matched?
By a stored Salesforce id first (e.g. SFDC_ContactId / SFDC_LeadId), then by email. Outbound, unmatched profiles create a new record and the id is written back for future updates.
I edited a profile but nothing reached Salesforce immediately — is that normal?
Outbound runs on its poll schedule. Use Sync now for an immediate run. Direct console/REST profile edits are caught by the next profile poll.
Why can't it create a Lead/Contact?
Salesforce requires LastName (plus Company for a Lead) to create a record. Map those fields, or existing records will still update.
Can I export my field mappings?
Yes — every Field Mapping tab has Export CSV and Export JSON for the selected object, in both directions.
Where is the configuration stored?
In the JCR under /settings/jcustomer-sfdc-connector, using typed node types (jcsfdcnt:*) so it's browsable in the Definitions / JCR browser.
Which Jahia version is required?
Jahia 8.2, with jExperience and a reachable jCustomer / Unomi service.
MIT License
Copyright (c) 2026 Stephane Monier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.