Allow additional data to be fed into External Data Source Fields

Title: Allow additional data to be fed into External Data Source Fields

  1. What is your original issue/pain point you want to solve?
    Currently, the only data that can be fed into an External Data Source Field Object’s Search URL is the search.term. Other data such as the customer details, organization or other object data are not accessible at that point.

  2. Which are one or two concrete situations where this problem hurts the most?
    This means that in order to filter External Data, variables have to be hard-coded into the Search URL.

  3. Why is it not solvable with the Zammad standard?
    This data does not appear to be available during ticket creation. So either multiple objects are required, or external methods need to be used to intercept and inject this information.

  4. What is your expectation/what do you want to achieve?
    Ideally, any ticket/user data (within reason) should be available to feed into the external data query.
    This would allow a single Object to be used that automatically filters it’s options based on the current customer, or what the customer has previously selected.

Your Zammad environment:

  • Average concurrent agent count: 60
  • Average tickets a day: 400
  • What roles/people are involved: IT Support and Site teams supporting 19 schools

Anything else which you think is useful to understand your use case:
In our specific environment, an example use case would be that natively, in order to provide a dropdown list of students, we currently require 19 objects and 19 core workflows to ensure that a teacher can find the right student. This, combined with the fact that External Data Source Field Objects are currently single-select only, means that we end up needing hundreds of objects and workflows, just to provide a simple, secure and accurate form to add 30 students to an exam group.

As mentioned, external methods to intercept and inject this information is technically possible. I have done this, and have a working system, that grabs the current customer email address and the organization (if the customer has at least one secondary org) and adds this data to the search URL. I’ve written two separate versions, as the new Desktop View functions differently to the current legacy web interface. This is not a long-term solution, as we need to be able to update Zammad without worrying about it breaking my bodges.

Legacy UI version;

(function() {
    console.log("Zammad Interceptor v9 (Agent UI + Payload Scraper) loaded.");

    let checkJquery = setInterval(function() {
        if (window.jQuery) {
            clearInterval(checkJquery);

            window.jQuery.ajaxPrefilter(function(options, originalOptions, jqXHR) {
                if (options.url && options.url.indexOf('external_data_source') !== -1) {
                    try {
                        let smuggledPrefix = "";

                        // --- 1. AGENT VIEW: Check Customer Information Sidebar ---
                        let agentCustomerEmail = "";
                        document.querySelectorAll('.sidebar-content .sidebar-block').forEach(block => {
                            let label = block.querySelector('label');
                            if (label && label.innerText.trim() === 'Email') {
                                // Extract the raw text nodes inside the block (ignoring the label itself)
                                let textNodes = Array.from(block.childNodes).filter(node => node.nodeType === Node.TEXT_NODE);
                                let emailText = textNodes.map(n => n.nodeValue.trim()).join('');

                                if (emailText.includes('@swale.at')) {
                                    agentCustomerEmail = emailText;
                                }
                            }
                        });

                        if (agentCustomerEmail) {
                            // Smuggle the customer's username!
                            smuggledPrefix = "USER:" + agentCustomerEmail.split('@')[0];
                        }
                        // --- 2. CUSTOMER VIEW: Check Org Dropdown ---
                        else {
                            const orgInput = document.querySelector('div[data-attribute-name="organization_id"] input.searchableSelect-main');
                            let currentOrg = orgInput ? (orgInput.getAttribute('title') || orgInput.value || "").trim() : "";

                            if (currentOrg) {
                                smuggledPrefix = "ORG:" + currentOrg;
                            }
                            // --- 3. CUSTOMER VIEW: Check Profile Avatar ---
                            else {
                                const profileAvatar = document.querySelector('a[href="#current_user"]');
                                if (profileAvatar) {
                                    let email = profileAvatar.getAttribute('title') || "";
                                    if (email && email.includes('@swale.at')) {
                                        smuggledPrefix = "USER:" + email.split('@')[0];
                                    }
                                }
                            }
                        }

                        // --- 4. Inject into the jQuery Data Payload ---
                        if (smuggledPrefix) {
                            if (options.data && typeof options.data === 'string') {
                                let params = new URLSearchParams(options.data);
                                let currentQuery = params.get('query') || '';

                                if (!currentQuery.includes('||')) {
                                    params.set('query', smuggledPrefix + '||' + currentQuery);
                                    options.data = params.toString();
                                    console.log("Interceptor: Smuggled perfectly ->", options.data);
                                }
                            }
                        }
                    } catch (e) {
                        console.error("Interceptor Error:", e);
                    }
                }
            });
        }
    }, 100);
})();

You can add other data to the search URL. Like you can add #{search.term}, you can also add, e.g., #{ticket.title} or #{ticket.custom_attribute}.

But here is one restriction: it’s only about the data from the database, not the “live” form data.

I’m moving this back from completed, because it caused OP to create a duplicate thread with the exact same content. I’d prefer not to cause dozens of duplicates so for the sake of this matter, I moved it…

1 Like

Thanks - Couldn’t see any way to reopen the topic.

You don’t have any in the solved category (because it usually isn’t needed). Next time you can appeal the post via moderation, if you’d like.