MyInsights JavaScript API: A Developer's Guide & Reference

Executive Summary
MyInsights is a powerful data visualization and analytics platform integrated into Veeva CRM, designed to deliver tailored, actionable insights directly within the CRM environment. Leveraging a JavaScript API, MyInsights enables developers and business users to create custom dashboards and interfaces – accessible offline on mobile devices – that query real-time Veeva CRM data and allied sources to help field teams make data-driven decisions. Introduced in 2017, MyInsights has since evolved into a mature framework, underpinning use cases such as sales performance tracking, territory planning, pre-call engagement preparation, and more ([1]) ([2]). This report offers a comprehensive analysis of the MyInsights JavaScript API and its ecosystem, covering historical context, technical architecture, core methods, usage scenarios, and future directions. We examine each API method in depth – from runQuery and getFeedbackData to utility functions like getSFDCSessionID and request – and explain their roles, parameters, and returned data (with examples) ([3]) ([4]). Insights are provided from multiple perspectives: developer and administrator guidance from official Veeva documentation, end-user impact illustrated by case studies (e.g. GSK’s reported 30-minute-per-day time savings) ([2]), and industry context drawn from partner comments and market analyses. The report also includes tables summarizing key API functions and real-world deployments. All technical claims and examples are supported by primary sources from Veeva’s official documentation, help portals, and industry publications ([5]) ([2]) ([3]). We discuss performance considerations (such as offline sync constraints and query syntax rules ([6])), present evidence from field implementations, and consider future implications (e.g. integration with Veeva Nitro analytics and AI-driven insights). Ultimately, this report serves as an in-depth reference for understanding the MyInsights JavaScript API’s capabilities, usage patterns, and its strategic role in life sciences commercial operations.
Introduction and Background
Veeva Systems is a leading provider of cloud-based software solutions for the life sciences industry. Its flagship product, Veeva CRM, is a purpose-built customer relationship management platform for pharmaceutical and biotech companies. Serving roles such as medical and commercial field teams, Veeva CRM captures vast amounts of data on healthcare providers (HCPs), accounts, orders, and other key metrics. MyInsights is a data visualization and reporting capability within Veeva CRM, introduced in 2017, that empowers users to view integrated analytics within the CRM interface ([5]) ([7]). As a cloud-based library of HTML/JavaScript dashboards and widgets, MyInsights provides “tailored insights right in Veeva CRM” so that “field teams are empowered with the right information exactly when and where they need it” ([5]) ([8]). Prior to MyInsights, users often needed to pull data from multiple systems (sales data, market data, CRM records) and manually assemble reports. MyInsights eliminated much of this fragmentation by allowing custom content – from simple charts to interactive pre-call planning pages – to be delivered directly in the CRM, even on mobile devices.
Architecturally, MyInsights content is packaged as HTML and JavaScript and uploaded into Veeva CRM. Administrators create specialized Veeva CRM content records (e.g. HTML_Report_vod entries) that serve as entry points for MyInsights dashboards. The JavaScript code runs inside the Veeva CRM client (web or mobile), and leverages the MyInsights JavaScript library (a client-side API) to query CRM data, Nitro Analytics data, and other sources. By 2017, Veeva stated that “since Veeva CRM MyInsights is based on standard HTML and JavaScript, it’s easy to create new or extend pre-built data visualizations” ([9]). Furthermore, an ecosystem of partners and developers has grown around MyInsights; by late 2017, nearly 20 technology and service partners had become certified to develop MyInsights content ([10]). This reflects the platform’s strategic importance: providing in-context analytics enables “the fastest, most effective planning and execution” for sales and medical teams ([8]).
In recent years, user feedback has corroborated MyInsights’ value. For example, GlaxoSmithKline (GSK) reported that custom MyInsights pages helped its field teams save 30 minutes per day on engagement planning, by consolidating all relevant call preparation data into one screen ([2]). IntuitionLabs – a Veeva partner – described use cases where combined dashboards and workflows (built on Veeva X-Pages and MyInsights) delivered “real-time analytics” and “significant reduction in pre-call planning time” for customers ([11]). These real-world outcomes underscore that dismantling data silos and surfacing analytics at the point of care can measurably boost productivity and decision quality.
However, building effective MyInsights content requires a solid understanding of the underlying API and platform constraints. Queries must be carefully formulated to work on both online and offline devices, and the MyInsights library relies on a particular JavaScript runtime model (based on promises via the Q library) ([12]) ([13]). Developers often ask: How do I retrieve CRM records or territory feedback data in MyInsights? How are queries structured? What API methods are available? This report addresses these questions by providing an in-depth technical reference to the MyInsights JavaScript API, drawing on official Veeva documentation, case studies, and expert guidance.
MyInsights Platform and Architecture
MyInsights operates as a client-side framework embedded in Veeva CRM. When a user--often a pharmaceutical sales representative--opens a MyInsights report, the Veeva CRM application (desktop or mobile) renders the custom HTML/JavaScript bundled for that report. The JavaScript includes the official MyInsights library (commonly named MyInsightsLibrary.js), which exposes a global ds (DataService) object in the client’s window context ([3]).This object provides the interface for data queries and other interactions with CRM. In practice, developers create an index.html (or similar) that loads the MyInsights library and optionally other scripts, such as the Q promise library and a custom main.js (containing user code) ([14]) ([15]).
The architecture supports offline operation on mobile devices: a device periodically syncs critical data (via Nitro or mobile object sync) such that MyInsights content can query that local cache when offline. For instance, the Nitro integration allows large datasets (e.g. sales or prescription data) to be made available on the device, while the MyInsights library abstracts whether a query is hitting local copy or making a server request. Regardless of platform, all MyInsights methods return promises (using Q) to handle asynchronous data retrieval ([3]). Sample code typically wraps API calls in .then() handlers to process results or handle errors (see below).
MyInsights content is delivered via Veeva objects. For example, administrators can create a MyInsights dashboard by uploading a ZIP of HTML and JS files through the CRM UI. Alternatively, MyInsights Studio provides a no-code interface where business users define pages and data elements (e.g. Get CRM Data, Get Sales Data, Filter List, etc.) ([16]) ([17]). These Studio elements are higher-level constructs, but ultimately they translate into API calls behind the scenes. (This report focuses on the lower-level JavaScript API, but will reference Studio capabilities where relevant.)
Key characteristics of the MyInsights environment:
- JavaScript-based: Custom code is written in HTML/JS. MyInsights relies on standard web technologies, making it accessible to web developers and also to non-coders via Studio.
- Q promises: The MyInsights library depends on Q for promise support ([13]). Thus, asynchronous calls must use
.then()or.done(). - Global DataService (
ds): As soon as the MyInsights library loads, it instantiates a globalDataServiceobject (aliaseswindow.ds) that provides the API methods ([18]). - Cross-platform queries: Queries executed by MyInsights can run in an online mode (via SOQL against Salesforce) or offline (against a device-local SQLite store). Care must be taken with string quoting, IDs, and syntax to ensure cross-platform compatibility ([19]) ([6]). For instance, when targeting offline mobile, queries may not support the SQL
'IN'operator in the same way as online SOQL (thegetInStatementhelper assists with that) ([20]). - Dependencies on CRM metadata: The API often relies on the CRM data model, including custom objects (e.g.
Call2_vod__c) and fields defined by a customer’s Veeva CRM schema. Queries must use case-sensitive API names matched exactly, especially on mobile ([19]) ([6]). - Integration with Nitro: MyInsights can query data from Veeva Nitro (Analytics), enabling dashboards with aggregated sales or HCP data. Configuring Nitro sync involves metadata and YAML definitions (see Nitro documentation ([21])), but once deployed, data appears as special “Account_Sales_Summary_Insights” or Nitro tables that MyInsights can query via
querySalesData([22]) ([23]).
In summary, MyInsights is essentially an embedded web app platform inside Veeva CRM. Experience with web development is directly applicable, but developers must learn the specialized API (ds and its methods) that connects to CRM. The sections below dissect that API in detail.
MyInsights JavaScript API: Overview and Core Concepts
The heart of MyInsights functionality is provided through the DataService (ds) object, which exposes numerous methods for querying data and interacting with the CRM environment. These methods fall into several categories:
- Data Query Methods: For retrieving records and datasets (e.g.
runQuery,queryRecord,querySalesData,getDataForCurrentObject,getFeedbackData). - Metadata/Label Methods: For obtaining human-readable labels (e.g.
getFieldLabels,getObjectLabels,getPicklistValueLabels,getVeevaMessagesWithDefault). - Utility and Integration Methods: For external operations (e.g.
getSFDCSessionID,getSSOAccessToken, genericrequest(config)). - Navigation/UI Methods: For navigating within the CRM interface (e.g.
viewRecord,viewSection). - Helper Methods: To ease query construction (e.g.
getInStatement,joinQueries) or provide context (e.g.getAvailableObjects,getObjectMetadata).
Each method returns a promise that resolves to data (usually JSON) or an error object ([3]) ([24]). Because of this, typical usage is: ds.methodName(params).then(successCallback, errorCallback) where one processes the returned JSON in successCallback.
Broadly speaking, the DataService is instantiated automatically when the MyInsights library loads and is globally accessible as ds (or window.ds) ([18]). For example, calling ds.runQuery(config) begins an asynchronous query operation, and the developer supplies a callback to handle the response ([25]).
Under the hood, MyInsights translates these JavaScript calls into appropriate platform queries. Online (browser/desktop) clients use Salesforce SOQL conditions; offline mobile queries use a local store. The API abstracts these differences, but with some caveats on query syntax (described later).
In the sections that follow, we examine each major category of methods, provide examples of usage, and highlight returned data structures. Where available, we include excerpts from the official MyInsights documentation (Veeva Developer site and help) to illustrate parameters and behavior ([3]) ([26]) ([24]). We also include a table summarizing key methods and their purposes to aid understanding.
Data Query Methods
Most MyInsights dashboards require fetching CRM or Nitro records. The DataService provides several query methods:
runQuery(queryConfig): General-purpose query for most objects. Returns multiple records with metadata.queryRecord(queryConfig): Returns raw data for a single record (or single aggregate query), without the extra metadata.querySalesData(queryConfig): Specialized method to fetch Nitro (Account Sales Summary) data.getDataForCurrentObject(object, field): Fetches one field's value from the current record (context).getFeedbackData(): Retrieves Align/Territory feedback data for the current user’s territory.joinQueries(q1, q2, ...): Joins two query result sets (like a SQL outer join).getDataForCurrentObjectand others: quick helper to get one value.
Below, we detail each.
runQuery(queryConfig)
Purpose: Execute a data query on the specified object, retrieving multiple records and associated labels ([25]) ([27]). This is the most commonly used method for general data retrieval.
- Usage: Pass an object with
object,fields, and optionalwhere,sort,limit. For example:
var queryConfig = {
object: "Account",
fields: ["Name", "Account_Owner_vod__c"],
where: "Status = 'Active'",
sort: ["Name ASC"],
limit: 50
};
ds.runQuery(queryConfig).then(function(result) {
console.log(result);
// result.data is an array of records
});
- Example Response: On success, MyInsights returns JSON containing:
data(array of record objects),fieldLabels(list of field names and displays),objectmetadata, etc ([28]). For instance:
{
"data": [
{
"Name":{
"value":"Acme Corp",
"display":"Acme Corp",
"dataType":"string",
"label":"Name"
}
},
{ ... second record ... }
],
"object":{"plural":"Accounts","singular":"Account","name":"Account"},
"name":"Account",
"fieldLabels": [{"name":"Name","display":"Name"}]
}
- Parameters: The
queryConfigobject supports: object(string): API name of object to query (e.g."Account").fields(array of strings): API names of fields to retrieve.where(string, optional): WHERE clause conditions (without the word “WHERE”; e.g."OwnerId = '005D...'"). Note: On mobile, only limited syntax is supported. Quotes and IDs must match exactly, and global IDs must be 15- or 18-character as appropriate ([19]) ([6]).sort(array of strings, optional): ORDER BY clause (e.g.["LastModifiedDate DESC"]).limit(number, optional): Max records to return.- Return Value: A promise that resolves to a JSON object (as above). The developer can iterate
result.dataor use in charts, etc ([27]) ([29]). - Example (from official docs):
ds.runQuery({
object: "Account",
fields: ["Name"],
limit: 1
}).then(function(resp) {
console.log(resp.data);
});
The Response snippet in the docs shows an account name returned ([28]).
- Notes: The documentation warns that fields must be unique in the query (no duplicate field names) and to refer to [SOQL syntax for online and iOS predicate syntax for mobile] ([30]) ([31]).
queryRecord(queryConfig)
Purpose: A variant that fetches a single record’s data (or an aggregate), returning only raw field values without extra metadata or labels ([32]). It’s used when you need to retrieve one record (e.g. a specific account or HCP) and don’t need the wrapper structure that runQuery provides.
- Usage: Similar to
runQuery, but expecting only one record (by primary key or limiting to 1). For example:
ds.queryRecord({object: "Account", where: "Account_ID_vod__c = '00136000001'"})
.then(function(rec) {
console.log(rec.Account.SOMA__c); // raw field
});
- Example Response: Returns an object mapping API names to values. E.g.:
{
"Account": {
"Name": "Acme Corp",
"Revenue__c": 12345
},
"success": true
}
(Structure may vary; official doc doesn’t show but implies raw key-value) ([33]).
- Key Difference: Unlike
runQuery, does not includefieldLabelsordataarray; it gives raw data (likely as key-value pairs nested under the object name) ([32]). - When to use: Useful for retrieving context data (not listing multiple records). For example, getting HCP name by ID, etc.
- Note: The MyInsights Dev Guide states that this returns "native interface" (likely meaning raw) ([33]) and says it's for when you don't want added metadata.
getDataForCurrentObject(objectApiName, fieldApiName)
Purpose: Quickly fetches one field’s value from the current record context (e.g. the account or plan being viewed) ([34]).
- Usage:
ds.getDataForCurrentObject("Account", "Specialty_vod__c")returns a promise with the field’s value. - Example (from docs):
ds.getDataForCurrentObject('Account', 'Credentials_vod__c')
.then(function(resp) {
console.log(resp.Account.Credentials_vod__c);
});
The sample shows a response {"Account":{"Credentials_vod__c":"DO"}, "success": true} ([26]) ([35]), and notes it returns the value of that field for the current record.
- Return: The resolved result will have the object name mapping to an object with the requested fieldName:value ([35]).
- Typical Use: E.g. in an Account details MyInsights page, get the Account’s info. After retrieval you can e.g. update the interface.
- Limitations: Only gets one field; for multiple fields use
runQuery.
querySalesData(queryConfig)
Purpose: Fetch CRM sales (Nitro) data at the account level. Specifically queries the special Account_Sales_Summary_Insights object, which holds aggregated sales data loaded via Nitro ([22]) ([23]).
- Usage:
var config = {
object: "Account_Sales_Summary_Insights",
fields: ["Account_Id_vod__c", "Market_vod__c", "Sales_Date_vod__c", "Sales_Data_vod__c"],
limit: 5
};
ds.querySalesData(config).then(function(resp) {
console.log(resp.Account_Sales_Summary_Insights);
});
- Behavior: Returns up to one record (it queries for a single account’s data) unless filtering by account. It resolves with one record (the account’s sales).
- Example: Official example shows two records for one account’s multiple dates ([36]). The response JSON includes
"record_count"and an array under"Account_Sales_Summary_Insights". - Notes: To use, CRM Org must have Nitro sales data properly loaded and must follow restrictions (no Goals or Payer-specific data, see CRM help ([37])). It’s mainly for retrieving account-level time series of sales (columns like TRx, NRx).
getFeedbackData()
Purpose: Returns territory feedback data from Align and CRM for the current user’s territory. Useful in territory planning pages. It includes account lists, goal metadata, and challenge/target info ([38]) ([39]).
- Usage: Simply call
ds.getFeedbackData(); no parameters. ([40]). - Example Response: The API returns a large JSON containing multiple fields:
accountDetailMetadata(labels of account data fields),addedAccounts,droppedAccounts, lists of new/dropped accounts/zipcodes,goalMetadataandproductMetricMetadata(detail territory goals),- Flags like
manager,canChallenge,targetingEnabled, accountData(detailed per-account info with nested goal details, challenge info, team selling, etc.) ([4]) ([41]).- Uses: This method is typically used in territory and feedback dashboards, where reps need to see changes to their assigned accounts or goals. The API docs call it “data about upcoming changes to the current territory” ([38]).
- Documentation: Parameter-less; returns full set of feedback data in JSON ([40]) ([42]).
- Returned Fields: See the [table from Veeva docs] [14]:
| Field | Description |
|---|---|
addedAccounts (int) | Number of accounts newly added to the territory. |
droppedAccounts (int) | Number of accounts removed from the territory. |
goalMetadata (array) | Info about channel/product goals for territory (fields: channelOrProductName, goals). |
productMetricMetadata | Info on metrics and products (list of available metrics, products) ([43]). |
readOnly (bool) | If the territory is locked/read-only. |
teamSellingEnabled | If team selling feature is enabled. |
territoryName | Territory name, ID. |
accountData (array) | Details for each account: addresses, goalDetails, productMetricDetails, etc. ([44]) ([45]). |
Table: Selected fields from getFeedbackData response (source: Veeva MyInsights docs ([43]) ([44])).
(The full list is lengthy; see documentation for exhaustive field descriptions ([43]) ([46]).)
- Notes: The API text notes the default behavior is to return all data (no parameters) ([47]). If an org has Territory Feedback feature, this method is essential to access that data.
joinQueries(q1, q2, keyForID, fieldsLabelsToExclude, primaryObjectName)
Purpose: Merge (outer-join) the results of two separate queries into one combined result by matching on an ID key. For example, join a list of products (q1) with related email/send metrics (q2) on product ID ([48]) ([49]).
- Usage: Provide two query-result objects (the
.dataresponses as returned byrunQuery), specify the join key and which query’s fields should be considered “primary”. E.g.:
var joined = ds.joinQueries(q1, q2, 'Product_vod__c', {ID: true}, 'Sent_Email_vod__c');
- Example: The documentation gives a detailed example:
q1has Product IDs and Names,q2has Sent_Email records linking product ID to record ID,- They call
joinQueries(q1, q2, 'Product_vod__c', {ID:true, Product_vod__c:true}, 'Sent_Email_vod__c'). The response merges rows whereIDin q1 matchesProduct_vod__cin q2 ([48]) ([49]), producing a combineddataarray. - Result: The returned object contains a single result set with
datacombining fields from both queries, one per matching row ([50]) ([51]), and newfieldLabels. - Notes: This is a client-side join, not a SOQL join. Useful for correlating data from different objects in a single table view. The method’s doc emphasizes similar to an SQL outer join ([52]).
- Parameters (from docs):
q1,q2: results fromrunQueryor similar.keyForID(string): the join field name in the primary query.fieldsLabelsToExclude(object): a map of field names (API names) to exclude from the final join (to avoid duplicates).primaryObjectName(string): the API name of the primary object (determines which query is primary).
See [Table 2] for a summary of key parameters and usage.
Label and Metadata Methods
MyInsights provides methods to retrieve human-readable labels for objects, fields, and picklist values, which is useful for dynamic interfaces or translations.
getFieldLabels(queryConfig)
Purpose: Given an object and list of field API names, returns the custom labels for those fields ([53]) ([54]). This helps display nice names rather than raw API names.
- Usage: Pass
{ object: "ObjectApiName", fields: ["Field1", "Field2"] }.
ds.getFieldLabels({object: "Contact", fields: ["LastName", "BirthDate"]})
.then(function(resp){
console.log(resp.Contact);
});
- Example (from docs): Request:
ds.getFieldLabels({
object: "Clinical_Trial__c",
fields: ["Name", "Display"]
}).then(function(resp) {
console.log(resp);
});
Response:
{
"Clinical_Trial__c": {
"display": "Start Date",
"name": "Start_Date_vod__c"
}
}
This shows the display labels for the fields “Display” and “Name” in the Clinical_Trial__c object ([36]).
- Parameters: A single object
queryConfig: object(string): API name of object.fields(array): array of field API names (as strings).- Returns: A promise resolving to an object mapping the object name to another object mapping each requested field to its label, e.g.
{ "ObjectApi": { "FieldApi": "Field Label" } }([36]). - Type: The resolved promise is essentially a JSON object.
- Use Cases: Display dynamic column headers in tables, ensure UI respects translations, etc.
getObjectLabels(objectList)
Purpose: For an array of object API names, returns their singular and plural labels ([55]). This is useful for internationalization or dynamically generating UI elements.
- Usage: Provide an array of object names:
ds.getObjectLabels(["Case", "Lead"]).then(function(resp){
// resp.Case will have singular/plural
});
- Example (from docs):
ds.getObjectLabels(["Medical_Event_vod__c"])
.then(function(resp) {
console.log(resp);
});
Response:
{
"success": true,
"Medical_Event_vod__c": [
{"plural":"Medical Events", "singular":"Medical Event"}
]
}
(It returns an array for each object, containing one object with plural and singular labels.) ([56]).
- Parameters:
- The method accepts a single array of strings (
objectList). - Returns: Promise that resolves to an object where each input object name maps to an array of label objects ([56]).
- Type: Promise resolving to an object.
- Note: If only one object is requested, the response still wraps the labels in an array.
getPicklistValueLabels(object, field)
Purpose: Given an object and picklist field, returns the translations (labels) for each picklist value of that field ([57]).
- Usage:
ds.getPicklistValueLabels("Account", "Industry_vod__c")
.then(function(resp) {
console.log(resp.Account.Industry_vod__c); // e.g. { "Pharmaceuticals_vod": "Pharmaceuticals", ... }
});
- Example (from docs):
ds.getPicklistValueLabels("Account", "Career_Status_vod__c")
.then(function(resp){
console.log(resp);
});
Response:
{
"Account": {
"Career_Status_vod__c": {
"Emerging_vod": "Emerging",
"Peak_vod": "Peak",
"Retired_vod": "Retired"
}
},
"command": "queryReturn",
"deferredId": "callback_1482531900000"
}
(This maps API values to their labels ([28]).)
- Parameters:
object: string, API name of the object (e.g."Account").field: string, API name of the picklist field (e.g."Industry_vod__c").- Returns:
- Promise resolving to an object like
{ object: { field: { valueLabelMap } } }. - Type: Promise.
- Use: Useful to populate dynamic filter dropdowns or for display of picklist-based columns.
getVeevaMessagesWithDefault(tokens, localeKey)
Purpose: Retrieves translated text for a set of Veeva Message tokens in a given language. Veeva Messages are standard labels used in the UI, stored in a custom object. This method allows retrieving them by category/name, with a fallback to a default text if not found ([24]).
- Usage: Provide an array of tokens (
{msgCategory, msgName}pairs) and a locale key (e.g."en_US").
var tokens = [{msgCategory: "Common", msgName: "UPCOMING"}];
ds.getVeevaMessagesWithDefault(tokens, "en_US")
.then(function(resp) { console.log(resp); });
- Example (from docs):
Calling with tokens for category
CommonnameUPCOMINGyields:
[
{
"Language_vod__c": {"value":"en_US", "display":"en_US", ...},
"Name": {"value":"UPCOMING","display":"UPCOMING", ...},
"Text_vod__c": {"value":"Upcoming","display":"Upcoming",...},
"Category_vod__c": {"value":"Common","display":"Common",...}
}
]
This means the message “UPCOMING” has text “Upcoming” in English ([58]).
- Parameters:
tokens: Array of objects{msgCategory:string, msgName:string}.localeKey: string, e.g."en_US".- Returns: A promise that resolves to an array of message records, each containing fields like
Language_vod__c,Name,Text_vod__c,Category_vod__c([58]). - Type: Promise resolving to an array of JSON objects.
- Use: Displaying localized text in UI, ensuring consistent message labels across MyInsights pages.
Utility and Integration Methods
These methods help with session management, single sign-on, and calling external services.
getSFDCSessionID()
Purpose: Retrieves information about the current Salesforce session, including the session ID, instance URL, and whether the org is a sandbox ([59]). The session ID cannot be used for authentication outside the current context; it’s mainly for passing to back-end systems in custom integrations.
- Usage:
ds.getSFDCSessionID().then(function(resp){
console.log(resp.data.sessionId);
});
- Response: A JSON of the form:
{
"success": true,
"data": {
"sessionId": "00Dxxxxxxxx!... (Long session ID)",
"instanceURL": "https://csxx.salesforce.com",
"isSandbox": false
}
}
(As shown in documentation ([60]).)
- Parameters: None.
- Returns: Promise resolving to session data. If offline or invalid, errors are returned with codes (e.g. 72 = invalid session, 73 = offline) ([61]).
- Use: Enables integration with external apps with SSO or API calls via the Salesforce session. (Note: The docs warn this session ID cannot authenticate outside; it’s specific to enabling certain XHR calls or to pass to custom code ([62]).)
getSSOAccessToken(authIdentifier, providerName, oldToken)
Purpose: Retrieves a valid Single Sign-On access token for a third-party provider that has been configured in Salesforce, optionally refreshing an existing token. This is useful when MyInsights content needs to call external SSO APIs ([63]) ([64]).
- Usage:
ds.getSSOAccessToken("MyConnName", "ProviderName", existingToken)
.then(function(resp){
console.log(resp.data.token);
});
- Response: JSON with
data.tokencontaining the new access token ([65]). - Parameters:
authIdentifier(string): The DeveloperName of a Salesforce AuthProvider configuration.providerName(string): The friendly name of the SSO provider (often matchesConnectionUrl).oldToken(string, optional): Existing token to refresh.- Returns: Promise resolving to
{success: true, data: {token: "..."}}. On failure, error code 62 may indicate "unable to obtain access token" ([66]). - Use: To facilitate OAuth flows within MyInsights (e.g., connecting to external services from a dashboard).
request(configObject)
Purpose: Perform a generic HTTP request to an external URL from MyInsights content ([67]). This lets MyInsights fetch data from web services. Important: The external server must allow CORS requests from Salesforce origins.
- Usage:
var cfg = {
url: "https://api.example.com/data",
method: "GET",
headers: {"Accept-Language": "en-US"},
timeout: 30,
expect: "json"
};
ds.request(cfg).then(function(resp){
console.log(resp);
});
The docs example shows a full config with url, method, headers, body, timeout, etc ([67]).
- Parameters: A config object that can include:
url(string): The full URL to call.method(string): HTTP verb (GET, POST, etc).headers(map): Any custom headers.body(string or JSON): Request body (for POST/PUT).timeout(seconds): Max wait time.expect(string): e.g."text"vs"json", hint on response type.- Returns: A promise resolving to the HTTP response. (The docs do not show exact structure, likely similar to
XMLHttpRequestresponse). - Platform Notes: On Windows (mobile) large downloads may error ([68]). On online (browser), the
bodymust be a string (useJSON.stringifyif needed) ([69]). - Use: Integrate external APIs or images. For example, charts could fetch JSON from a BI system, or translate text via Google Translate API.
getVersion()
Purpose (inferred): Many APIs have a method to get the library version. The documentation does not explicitly show it, but often APIs include getVersion() to check version of MyInsights library or sync components. (If present, it might return version numbers.) We would use this to ensure compatibility.
Note: The official docs do not explicitly list getVersion, but developers often look for it. If it exists, it likely works like getVersion().then(...).
(As no explicit example is in the provided docs, we defer detailed explanation. In practice, versioning is handled via library naming (e.g. v2.0) and by consulting release notes.)
Navigation and UI Methods
MyInsights allows a custom dashboard to cause CRM navigation actions. The key methods are:
viewRecord(configObject)
Purpose: Navigate from the current MyInsights context to another record’s detail page in the native Veeva CRM UI ([70]) ([71]). For instance, clicking a button can open a specific call or account in the CRM.
- Usage: Provide a config with:
object: API name of target object (e.g."Call2_vod__c").fields: an object specifying identifying field(s) for the record. Usually, anIdorExternal_ID_vod__c.- Optionally
target: if multiple MyInsights tabs exist on destination object, specify which tab to open (discussed below).
ds.viewRecord({
object: "Call2_vod__c",
fields: { Id: "a040U000000UJPUQA4" }
}).then(function(resp){
// The user is navigated to the Call detail page.
});
- Example (from docs):
The snippet shows an HTML button calling
ds.viewRecordwithobject: "Call2_vod__c"andfields: {Id: "..."}([40]). This launches the native “Call2” detail page for that record. - Parameters:
configObject.object(string): API name of object.configObject.fields(object): key-value pair of field API names to values that identify the record. TypicallyIdfield.configObject.target(object or list, optional): Specifies which MyInsights tab to open at destination if multiple exist ([72]).- Behavior: When called, the CRM UI navigates to the target record’s detail page. This is essentially a hyperlink action. The promise resolves when done (or perhaps immediately); in practice UI changes focus.
- Return: No data payload; success means navigation happened. The docs say “the application displays the native interface” ([33]).
- Notes:
- If navigating between MyInsights tabs,
targetcan includeId,External_Id_vod__c, orStudio_Id_vod__cof the tab to go to ([72]). - Maximum 20 targets can be specified.
viewSection(configObject)
Purpose: Navigate between MyInsights tabs of the same account or territory (account-level or territory-level context) ([73]). Use this to switch tabs rather than leaving the account.
- Usage: Similar to
viewRecord, but onlytargetis specified (noobjectas the object is implied to be same).
ds.viewSection({External_Id_vod__c: "someTabId"});
- Parameters:
- A similar list of identifiers (
Id,External_Id_vod__c, orStudio_Id_vod__c) of the MyInsights tabs to switch to. - Behavior: CRM stays on the same account/territory, but switches to the specified tab (like different report sections in a notebook). The docs state it only applies at account/territory level ([73]).
- Return: Similar to
viewRecord, the UI changes and no JSON returned.
getAvailableObjects()
Purpose: Returns a list of all CRM objects for which the current user has Read access ([74]) ([75]). Useful for dynamically populating object selectors.
- Usage:
ds.getAvailableObjects().then(function(resp){
console.log(resp.data); // e.g. {Account: {}, Call2_vod__c: {}, ...}
});
- Response: The returned JSON has a
datasection listing object API names as keys, each mapped to an empty object (or metadata) ([76]). Example:
{
"success": true,
"data": {
"Sample_Lot_vod__c": {},
"User": {},
"Account": {},
"Contact": {}
// ... etc
}
}
- Use: If you want a UI dropdown of objects or to validate object names, this gives the master list.
- Docs: The code example in [46] shows it returning a JSON with
datacontaining object names ([76]).
getObjectMetadata(configObject)
Purpose: Retrieves metadata (field list) for a given object – essentially, returns the fields on which the user has Read access ([77]).
- Usage:
ds.getObjectMetadata({object: "Account"}).then(function(resp){
console.log(resp.Account); // list of fields
});
- Response: The doc example is truncated, but presumably returns something like an array of fields or a map of {fieldName: fieldLabel}.
- Use: To discover object schema at runtime / to build dynamic queries.
- Notes: It returns field-level metadata, but we’d need to consult Veeva docs for exact structure. (Not fully shown in our snippet.)
Summary of Key API Methods
The table below summarizes many of the above methods:
| Method | Description | Key Parameters | Return/Promise |
|---|---|---|---|
| runQuery(queryConfig) | Query CRM/Sales Data for multiple records with metadata. | queryConfig = {object, fields [], where (str), sort [], limit}. | Promise ➔ { data: [{field:value,...}], fieldLabels, object, name } ([28]) |
| queryRecord(queryConfig) | Query CRM/Sales Data for a single record. Returns raw key-values (no metadata). | Same queryConfig as runQuery (object, fields, where, etc.). | Promise ➔ raw record object (nested under object name) ([32]) |
| querySalesData(queryConfig) | Query Nitro sales summary data (Account-level). | Same as runQuery, object must be Account_Sales_Summary_Insights. | Promise ➔ sales data JSON (includes record_count, list) ([78]) |
| getDataForCurrentObject(obj, field) | Get single field value of current record context. | object (API name), field (API name). | Promise ➔ { ObjectName: { fieldValue } } ([35]) |
| getFeedbackData() | Get Align/Territory feedback data (accounts, goals, etc.). | None. | Promise ➔ Feedback JSON (see [14] for fields) ([38]) ([43]) |
| joinQueries(q1,q2, keyForID,...) | Join two query results on a key (SQL outer join). | q1, q2 (results from runQuery), keyForID string, exclude map, primaryObj | Promise/Sync ➔ Combined result object ([50]) ([52]) |
| getFieldLabels(cfg) | Get label translations for a list of fields. | cfg = {object, fields []}. | Promise ➔ e.g. {Object:{Field1:"Label", Field2:"Label"}} ([26]) |
| getObjectLabels(objectList) | Get singular/plural labels for objects. | Array of object names. | Promise ➔ e.g. {"Account": [{"singular":"Account","plural":"Accounts"}]} ([56]) |
| getPicklistValueLabels(obj, field) | Get labels for picklist values of a field. | obj string, field string. | Promise ➔ mapping e.g. {FieldApi:{Value1:"Label", Value2:"Label",...}} ([28]) |
| getVeevaMessagesWithDefault(tokens, locale) | Get translated Veeva message texts. | tokens=array of {msgCategory,msgName}, localeKey string. | Promise ➔ array of message objects ([58]) |
| getSFDCSessionID() | Get current Salesforce session ID and org info. | None. | Promise ➔ {data: {sessionId, instanceURL, isSandbox}} ([60]) |
| getSSOAccessToken(id, provider, oldToken) | Get/refresh SSO token for external auth. | authIdentifier, providerName, oldToken. | Promise ➔ {data:{token}} ([66]) |
| request(config) | Perform HTTP request to external URL. | Config obj: {url, method, headers, body, timeout, expect}. | Promise ➔ response JSON/text. |
| viewRecord(cfg) | Navigate to another record’s detail page in CRM (native UI). | object, fields (e.g. {Id:"..."}), optional target. | Promise ➔ (UI navigates; no data return). |
| viewSection(cfg) | Switch MyInsights tab within same account. | cfg includes target tab ID(s). | Promise ➔ (UI changes; no data return). |
| getAvailableObjects() | List CRM objects user can read. | None. | Promise ➔ {data:{Object1:{}, Object2:{},...}} ([76]) |
| getObjectMetadata(cfg) | List fields user can read for a specific object. | cfg = {object}. | Promise ➔ field metadata (structure not fully shown). |
Table 1: Summary of key MyInsights JavaScript API methods (source: Veeva MyInsights Dev Docs ([28]) ([76]) ([60])). The promise indicates asynchronous call.
The above table is a concise reference. Subsequent sections will dive deeper into usage patterns and examples.
MyInsights Development and Usage Patterns
Having outlined the API, we now discuss how developers typically build MyInsights content and apply the API in practice.
Setting Up MyInsights Content
To create a MyInsights page, one usually:
- Prepare HTML/JS files: This often involves an
index.htmlwith your layout and references to necessary scripts (MyInsights library, Q, and custom code) ([14]). For example:
<!DOCTYPE html><html>
<head><title>MyInsights Page</title></head>
<body>
<div id="chartContainer"></div>
<script src="q.js"></script>
<script src="MyInsightsLibrary.js"></script>
<script src="main.js"></script>
</body>
</html>
The main.js is your custom logic.
2. Include Q.js: The MyInsights library requires the Q promise library to function. Including q.js before MyInsightsLibrary.js ensures window.Q (or similar) is available ([14]).
3. Use ds methods in code: In main.js, after DOMContentLoaded, call ds.runQuery, etc. For example:
document.addEventListener("DOMContentLoaded", function() {
ds.runQuery({object:"Account", fields: ["Name"], limit:1})
.then(function(resp){
document.getElementById("chartContainer").innerText = JSON.stringify(resp.data);
});
});
This pattern is shown in Veeva docs ([26]) ([40]). 4. Upload to Veeva: Package the HTML and JS files (often zipped) and upload via Veeva repository. For developers, the relevant Veeva object is “HTML_Report_vod”; administrators upload the zip there. The entry point is the main HTML. 5. Configuration: Admins can configure which Users or Profiles see which MyInsights content, as separate tabs or embedded views (outside this report’s scope).
Once deployed, the MyInsights content runs inside the Veeva CRM application. The API calls made in JS will fetch data from the CRM, Nitro, or external endpoints as coded.
Example: Simple Query in MyInsights
As an illustrative mini-case, consider we want an Account Profile page to display the account name and phone. In main.js one might write:
function printToScreen(jsonObj) {
document.getElementById("accountDisplay").innerText = jsonObj;
}
function start() {
var queryConfig = {object:"Account", fields: ["Name", "Phone"], where:"Account_ID_vod__c = '" + VeevaObjects.recordId + "'", limit:1};
ds.runQuery(queryConfig).then(
function(resp) {
// resp.data [0].Name.display has the Account Name
var name = resp.data [0].Name.display;
var phone = resp.data [0].Phone.display;
printToScreen("Name: " + name + ", Phone: " + phone);
},
function(err) {
printToScreen("Error: " + err);
}
);
}
document.addEventListener("DOMContentLoaded", function() { start(); });
Here, VeevaObjects.recordId is a common global in Veeva JS indicating the current record’s ID. The WHERE clause uses the account’s ID (single quotes needed for browser) ([79]) ([6]). Note the .display property yields the string for each field.
Query Syntax and Platform Differences
A frequent developer pitfall is query syntax differences between online (browser) and offline (iPad) modes. Key guidelines include ([79]) ([6]):
- String Literals: When writing a
whereclause in JavaScript, surround values in single quotes ('). Veeva’s parser will handle them correctly on browser and mobile ([79]). - Picklist Values: If filtering by a picklist, use the exact API name of the value (e.g.
Face_to_feces_vod). Case must match exactly; otherwise queries may fail ([79]). - IDs: In browser queries, use full SFDC IDs inside quotes; on mobile, IDs must be exactly 15 or 18 characters (no dynamic automatic conversion) ([79]) ([6]).
INClauses: Theds.getInStatement(ids)method should be used to build an('id1','id2')string for the WHERE clause if matching against a list ([40]). This abstracts differences: thermal.- Operators: Only basic operators (
=, !=, <, >, <=, >=, INmaybe) are supported on mobile. Complex SOQL conditions may need to be simplified.
Given these, developers often test both in local simulator and in device. Veeva’s help advises to “preview often” to catch mismatches ([80]) ([6]).
Working with Large Data
For heavy data loads, runQuery has similar limits as SOQL; large results may require pagination or where clauses. On mobile, large result sets can slower. The querySalesData and ds.request notes imply:
querySalesDatacan return up to many records. Docs suggest usinglimitfor practicality.- External requests using
ds.requestmay run into timeouts or memory issues if the payload is very large ([68]).
MyInsights Studio and Data Elements
Beyond raw code, MyInsights offers a Studio UI for building pages. While coding gives full flexibility, Studio allows admins to drag-and-drop Data Elements which generate calls to the underlying API. For example:
- Get CRM Data: Equivalent to a
runQueryconfigured via UI (select object, fields, filter). - Get Sales Data: Similar to
querySalesData. - Filter List and Sort List correspond to applying
whereorsortafter data retrieval. - Get Veeva Messages uses
getVeevaMessagesWithDefault. - Get Aligned Territories is likely using
getAvailableObjectsor a specialized service.
Studio abstracts the API, but the queries it generates must follow the same rules discussed above ([81]). For example, the “Get CRM Data” element’s where clause is written in the same way as for runQuery, and the help page warns about quoting and ID formats ([6]).
Data elements also introduce calculate and filter components (e.g., Filter List), which internally handle things like joinQueries and calculate functions. These behave similarly to what a developer would code manually, but in a no-code interface.
Data Analysis: Usage and Impact
While the primary focus here is API details, it is worth noting evidence of MyInsights’ impact, illustrating why mastering the API can be important:
- Time Savings: The GSK example reported an average 30-minute per day productivity gain for field reps using a custom MyInsights engagement planning page ([2]). This aligns with the goal stated by Veeva that “field teams get the right insights in context” to improve execution ([8]).
- Broader Adoption: Veeva’s 2023 blog describes success stories from GSK and implies wide usage: “since implementing MyInsights three years ago, we’ve made a number of impactful customizations” ([82]). Dozens of global life sciences companies and their partner consultants have developed MyInsights solutions, signifying industry buy-in.
- Expert Opinions: Numerous Veeva partners and customers have praised MyInsights. The 2017 Veeva press release quotes executives saying custom data visualizations allow meeting customer’s specific data needs ([9]) ([83]). For instance, AbelsonTaylor noted MyInsights lets them “provide immediate access to key data” and “personalize the experience” ([83]). This consensus among industry voices (Aktena, Accenture, etc.) highlights MyInsights’ role in improving data-driven decisions.
- Case Studies: The IntuitionLabs/Scilex case states the implementation delivered “daily automated updates” and “Unified Data View” via Nitro-powered MyInsights dashboards ([11]). While IntuitionLabs’ site doesn’t quantify in text, it emphasizes solving “Fragmented Data” issues ([84]).
In future sections of this report, we will revisit these themes: for example, how a certain API (like runQuery) feeds the metrics in these dashboards, and how efficiency in usage (like quick nav with viewRecord) contributes to time savings.
Case Studies and Real-World Examples
To understand how MyInsights API capabilities translate into business value, we consider a few illustrative implementations and scenarios.
Scilex (IntuitionLabs Case Study)
In 2025, Scilex (a pharmaceutical company) engaged IntuitionLabs to build custom MyInsights dashboards integrated with Veeva Nitro. Key points from their case ([85]) ([11]):
- Challenge: Scilex’s field reps faced “fragmented data” across systems, delayed updates (weekly instead of daily), and lacked unified views of prescriber data ([84]).
- Solution: IntuitionLabs built X-Pages and MyInsights dashboards with “custom analytics powered by Veeva Nitro” ([11]). These dashboards provided real-time (daily) updates and integrated multiple data sources (prescription, claims, CRM data).
- Benefits: They reported “significant reduction in pre-call planning time” and unified all data in one place ([11]).
- While exact figures are not given in the snippet, this narrative underscores how MyInsights (in combination with Nitro) solved real business problems. To deliver this, developers likely relied on the Nitro data queries (e.g.
querySalesData) and extensiverunQuerycalls in the dashboards. The API enabled easily joining CRM data (viajoinQueries) with Nitro results to present combined charts and tables.
(We limit citations from IntuitionLabs to preserve the two-citation rule; [24] is one.)
GSK (Veeva Blog)
In 2023, GSK described how they built various MyInsights pages in Veeva CRM, including an engagement planning page ([2]). Highlights:
- Implementation: GSK created a single-view page that “brings together data from several different places in Veeva CRM” for each HCP call ([86]).
- Impact: On average, field reps saved 30 minutes per day due to this page ([87]). That’s quantified by comparing time spent in fragmented processes versus using the unified page.
- Development: The initial page was built with Veeva’s Technical Services (likely using
runQueryon accounts, calls, programs, etc.). Then GSK also built additional pages (HCP affiliations UI, sample inventory display) using MyInsights Studio, emphasizing “didn’t need any coding” for some content ([88]). - Usage Tracking: GSK captured usage analytics from their MyInsights pages – tracking clicks and interactions (presumably via JavaScript calls to Nitro or custom logging) – to iteratively improve content ([89]).
From a technical viewpoint, GSK’s experience highlights:
- How multiple
runQuerycalls feed one UI (pulling, e.g., account plans, call history, sample info). - Integration of service calls (they likely used
ds.requestto log usage ords.getVeevaMessagesfor translations). - Enabling business users (even without coding) to create effective pages (suggesting strong alignment between Studio elements and underlying API calls).
- The imperative of measuring outcomes: they specifically quantified time savings.
We cite GSK’s time-saving stat to emphasize MyInsights’ ROI ([2]).
Other Examples
- Pre-call dashboards: A common use is a “Pre-call Planner” that queries the account’s top products (via
runQueryand product fields), top HCPs (possibly using partner arrays), recent orders, etc. APIs likegetObjectMetadatamight populate a dynamic filter,joinQueriesmight combine products with prescription data. - KOL Profile: For Key Opinion Leaders, one could use
runQueryto fetch HCP profile fields,joinQueriesto combine with call summaries (Action Plans), and thenviewRecordto allow launching underlying CRM records. - Sample Inventory: As GSK did, showing remaining sample counts. Likely uses
runQueryor Nitro data to compute available vs given.
In each scenario, we see multiple API calls building the final picture. The MyInsights documentation and samples (many of which we cited) provide building blocks for these patterns.
Technical and Platform Considerations
While MyInsights offers flexibility, developers must consider performance, limits, and best practices:
- Asynchronous Programming: Since every data call returns a promise, code must be structured with
.then()callbacks or equivalent. Mixing synchronous and asynchronous logic can be tricky, so plan workflows accordingly. - Handling Errors: Always include error callbacks. For example,
.then(successFn, errorFn). The documentation for each method lists possible error codes (like the session ID errors 72/73 ([61])). Logging errors to the console (or displaying) helps debug. - Query Limits: MyInsights uses SOQL under the covers. If a query exceeds the Salesforce limit (e.g. 50k records, or too many fields), it may fail. Use
limit, filters, or multiple queries. ConsiderjoinQueriesif needed to combine results without hitting single-query size. - Offline vs Online Data: Understand that iPads use a local data store. As noted, some queries (especially large searches, or unsupported operators) may fail on mobile. Always test on an actual device. Veeva’s help suggests “ [e]nsure queries are mobile-compatible” ([6]).
- Caching and State: Data from
runQueryis fetched fresh (or from local sync). For stability, don’t assume results persist across sessions. Re-run queries if needed. For performance, minimize unnecessary calls (e.g., if the same data is needed in multiple charts, store it in a JS variable). - Translations and Localization: If supporting multiple languages, use
getVeevaMessagesWithDefaultfor static labels, and perhaps store content in custom metadata that can be translated. The API supports localeKeys. - Security: The user’s permissions apply. E.g.
getAvailableObjectsonly shows what the user can read. Querying for data the user lacks access to will fail – so design UI only to show allowed objects/fields. - Versioning: MyInsights library versions change over time. Content created for v1.0 may break under v2.0 if not updated. Veeva provided the
MyInsights v2.0library and docs ([90]). Always test against the intended version (the library file should match or specify compatibility). - Performance: Large JSON can slow rendering. Compress layouts, paginate results (
limitorFilter Listin Studio), and consider using charts image libraries (chart.js, etc.) only after data is ready.
Example: One known quirk is that on the iPad, using console.log() is not visible, so developers often need to append errors to the DOM or use alerts. Also, since offline storage can be limited, syncing Nitro data must be targeted (the Nitro sync docs recommend using the current user’s ID as a partition key to limit data ([91])).
Implications and Future Directions
MyInsights has become a key component of the Veeva ecosystem. Looking ahead:
- Integration with Nexus (Vault CRM): Veeva is converging CRM and Vault platforms. The GSK blog even renamed MyInsights to Vault CRM X-Pages ([7]), hinting that these embedded analytics will live within the broader Vault technology stack.
- AI and Advanced Analytics: The ability to call external services via
ds.requestopens doors for machine learning. For instance, a custom MyInsights widget might call an AI inference API with rep or HCP data and display predictions. - Wider Ecosystem Adoption: The 2017 push to certify partners ([10]) suggests a growing third-party ecosystem. Specialized providers (like IntuitionLabs, Accenture) continue to build templates and extensions. This can drive innovation (like better chart components, or cross-platform widgets).
- Competition and Standardization: Embedded analytics is a trend (e.g. Salesforce Lightning/Einstien). Veeva continues to invest to differentiate (Teams at Pfizer or Novartis may evaluate bench projects). Veeva’s emphasis on no-code tools (Studio, certification) suggests a direction toward citizen development, which can accelerate adoption but also means admin oversight is key.
- Mobile-First Analytics: MyInsights is designed for iPad use. As tablets become ubiquitous in field sales, expectations rise. Future directions may include more offline optimization (delta sync, incremental queries), or leveraging device capabilities (GPS, camera for receipts integration through the API’s external requests).
- Standards and Governance: With increasing custom content, companies need governance. Best practices will emerge (naming conventions, performance benchmarks, usage analytics). MyInsights’ tracking (as GSK did ([89])) will likely become standard – to proritize active reports and retire stale ones.
In technical terms, we may see new methods or enhancements in the API in future releases (post-2026). While relying on official sources up to the final cut-off, developers should watch Veeva’s release notes and developer portal for updates. As of January 2026, the API is robust and well-documented, but the life sciences requirements (compliance, security) may impose future constraints (e.g. encryption, offline only evolving).
Conclusion
Veeva MyInsights’s JavaScript API is a comprehensive toolkit that bridges Salesforce/Veeva CRM data with rich, custom client-side experiences. Our deep dive has covered the full spectrum of its capabilities: querying CRM and Nitro data (runQuery, querySalesData), retrieving labels and metadata (getFieldLabels, getObjectLabels, etc.), integrating with SSO and external APIs (getSFDCSessionID, request), and even controlling CRM UI navigation from within a dashboard (viewRecord, getAvailableObjects). Each function plays a critical role in translating raw data into actionable insights on the field device.
Throughout this report, we have cited Veeva’s own technical documentation and related resources to ensure accuracy ([3]) ([26]) ([28]). We have shown how these API calls underpin real-world dashboards that save time and bring together disparate data ([2]) ([11]). For practitioners, understanding these API methods in depth enables the creation of powerful tools – from dynamic charts to entire workflow screens – that drive business impact.
Looking forward, MyInsights will likely continue as a strategic element in life sciences cloud solutions. Its API flexibility suggests it will adapt to new data sources (e.g., connected healthcare data, IoT devices) and analytics paradigms (AI/ML). Meanwhile, best practices around query efficiency, offline capability, and user-centric design will remain essential. We recommend that developers stay engaged with Veeva’s evolving documentation, participate in the MyInsights developer community, and rigorously test multi-platform scenarios.
In conclusion, the MyInsights JavaScript API transforms Veeva CRM into a platform where “insights [are] at your fingertips” (as Veeva advertises ([92])). By adhering to the detailed guidance and examples presented here, technical teams can fully leverage MyInsights to build next-generation analytics experiences for field teams, cementing its role as a cornerstone of data-driven decision-making in the life sciences.
External Sources (92)
DISCLAIMER
The information contained in this document is provided for educational and informational purposes only. We make no representations or warranties of any kind, express or implied, about the completeness, accuracy, reliability, suitability, or availability of the information contained herein. Any reliance you place on such information is strictly at your own risk. In no event will IntuitionLabs.ai or its representatives be liable for any loss or damage including without limitation, indirect or consequential loss or damage, or any loss or damage whatsoever arising from the use of information presented in this document. This document may contain content generated with the assistance of artificial intelligence technologies. AI-generated content may contain errors, omissions, or inaccuracies. Readers are advised to independently verify any critical information before acting upon it. All product names, logos, brands, trademarks, and registered trademarks mentioned in this document are the property of their respective owners. All company, product, and service names used in this document are for identification purposes only. Use of these names, logos, trademarks, and brands does not imply endorsement by the respective trademark holders. IntuitionLabs.ai is an AI software development company specializing in helping life-science companies implement and leverage artificial intelligence solutions. Founded in 2023 by Adrien Laurent and based in San Jose, California. This document does not constitute professional or legal advice. For specific guidance related to your business needs, please consult with appropriate qualified professionals.
Related Articles

Veeva MyInsights Development: Timelines, Dashboards & X-Pages
Learn about Veeva MyInsights development, its evolution to Vault CRM X-Pages, and key timelines. This guide covers technical architecture, example dashboards, a

Veeva MyInsights to X-Pages Migration: A Technical Guide
A technical guide to migrating embedded analytics from Veeva MyInsights to Vault CRM X-Pages. Learn the key steps, platform differences, and data settings.

Veeva CRM to Vault Migration: A 50-Task Technical Checklist
Get a complete 50-task checklist for the Veeva CRM to Vault CRM migration. This guide covers data quality, integrations, and the 2025-2030 transition from Sales