Newer Version Available

This content describes an older version of this product. View Latest

Considerations for Custom Interactions

Easily create and log custom interactions on your managed package using Apex. As subscribers interact with your package and your Apex code is executed, the custom interactions that you defined are logged. Retrieve your custom interactions in your package's AppExchange App Analytics usage logs and usage summaries.
Available in: both Salesforce Classic and Lightning Experience
Available in: Enterprise, Performance, Unlimited, and Developer Editions

As an ISV partner, the complex features that you develop in your managed packages could involve multiple actions on different objects, callouts to Apex functions, and much more. It can be difficult to interpret how your subscribers interacted with specific packaged components via your downloaded App Analytics package usage logs and summaries.

To provide you with more clarity about your subscribers’ events in custom ways and at different granularity levels, create custom interactions in your managed packages using Apex.

With Apex custom interactions, you can discover:

  • Which app feature a user interacted with
  • How users flowed through a specific user journey
  • Which UI components a user interacted with

Keep these considerations in mind:

  • A custom interaction can appear for a given user request up to 50 times. This limit avoids flooding the logs due to large loops.
  • We recommend that you don’t call IsvPartners.AppAnalytics.logCustomInteraction from inside a loop.
  • If the IsvPartners.AppAnalytics.logCustomInteraction method is called from a running Apex test, no AppExchange App Analytics package usage log or package usage summary data is produced.

Log Custom Interactions

Create and log custom interactions with your managed package using Apex.
  1. In your packaged Apex code, include Apex enums that are associated with the events that you want to log as custom interactions.
  2. In your Apex code, invoke IsvPartners.AppAnalytics.logCustomInteraction, using the enums that you created.
  3. Test your code by running it in your development environment and checking your debug logs to be certain that the custom interactions you created are being logged. Ensure that your debug log levels for Apex Code are set to FINE.
  4. After you’re finished with your implementation, publish a new version of your managed package.
  5. After subscribers install your package, retrieve your package usage logs and package usage summaries. Filter your package usage log data on custom_entity_type by CustomInteractionLabel, and on log_record_type by CustomInteraction. Or filter your package usage summary data on custom_entity_type by CustomInteractionLabel.
  6. Analyze your custom interaction data.

Example

Let’s suppose you have a Lightning Web Component (LWC). Your LWC provides a list of related contacts for each Account record, uses a table layout, and is wired to an Apex class. You add a new card layout to your LWC. To track how well users are adopting this new layout, you log an interaction when a user switches between layouts.

An example Lightning Web Component in table format showing these columns: Name, Title, Email, and Phone, plus Table and Card buttons

In your code, include Apex enums and invoke IsvPartners.AppAnalytics.logCustomInteraction.

Your LWC HTML code:

1<template>
2    <div
3        class="slds-var-m-top_medium slds-var-m-bottom_x-large slds-box slds-theme_default"
4    >
5        <h2 class="slds-text-heading_medium slds-var-m-bottom_medium">
6            Change data view
7        </h2>
8    <!-- Button group: simple buttons -->
9    <lightning-button-group class="slds-var-m-bottom_medium">
10        <lightning-button
11            label="Table"
12            variant={tableVariant}
13            onclick={handleClick}
14    ></lightning-button>
15        <lightning-button
16            label="Card"
17            variant={cardVariant}
18            onclick={handleClick}
19        ></lightning-button>
20    </lightning-button-group>
21    <template lwc:if={displayTable}>
22        <lightning-datatable
23            key-field="id"
24            data={records}
25            columns={columns}
26        ></lightning-datatable>
27    </template>
28    <template lwc:if={displayCard}>
29        <div class="slds-grid slds-wrap slds-grid_pull-padded-small">
30            <template for:each={records} for:item="contact">
31        <div
32            class="slds-col slds-small-size_1-of-1 slds-large-size_1-of-2 slds-var-p_small"
33            key={contact.id}
34        >
35            <lightning-card
36                variant="Narrow"
37                title={contact.name}
38                icon-name="standard:contact"
39            >
40                <div class="slds-var-p-horizontal_small">
41                    <p>{contact.name}</p>
42                    <p>{contact.title}</p>
43                    <p>
44                        <lightning-formatted-phone
45                        value={contact.phone}
46                        ></lightning-formatted-phone>
47                    </p>
48                    <p>
49                        <lightning-formatted-email
50                        value={contact.email}
51                        ></lightning-formatted-email>
52                   </p>
53                </div>
54            </lightning-card>
55        </div>
56    </template>
57    </div>
58    </template>
59     </div>
60</template>

Your LWC JavaScript code:

1import { LightningElement, wire, api } from "lwc";
2import { getRelatedListRecords } from "lightning/uiRelatedListApi";
3import logInteraction from "@salesforce/apex/LogContactListInteraction.log";
4
5export default class ContactList extends LightningElement {
6    @api recordId;
7    error;
8    records;
9    displayTable = true;
10    displayCard = false;
11    columns = [
12        { label: "Name", fieldName: "name" },
13        { label: "Title", fieldName: "title" },
14        { label: "Email", fieldName: "email", type: "email" },
15        { label: "Phone", fieldName: "phone", type: "phone" }
16    ];
17    @wire(getRelatedListRecords, {
18        parentRecordId: "$recordId",
19        relatedListId: "Contacts",
20        fields: [
21            "Contact.Name",
22            "Contact.Id",
23            "Contact.Phone",
24            "Contact.Email",
25            "Contact.Title"
26    ],
27    sortBy: ["Contact.Name"]
28    })
29    contactList({ error, data }) {
30        if (data) {
31        this.records = data.records.map((item) => {
32            return {
33              name: item.fields.Name.value,
34              id: item.fields.Id.value,
35              title: item.fields.Title.value,
36              email: item.fields.Email.value,
37              phone: item.fields.Phone.value
38              };
39        });
40        this.error = undefined;
41    } else if (error) {
42        this.error = error;
43        this.records = undefined;
44        }
45    }
46
47    handleClick(event) {
48        if (event.target.label.toLowerCase() === "table") {
49        this.displayTable = true;
50        this.displayCard = false;
51            logInteraction({ type: "table" });
52        } else if (event.target.label.toLowerCase() === "card") {
53              this.displayTable = false;
54              this.displayCard = true;
55              logInteraction({ type: "card" });
56        }
57    }
58    get cardVariant() {
59        return this.displayCard === true ? "brand" : "";
60    }
61    get tableVariant() {
62        return this.displayTable === true ? "brand" : "";
63    }
64}

Your Apex class:

1public class LogContactListInteraction {
2    public Enum ContactListLayouts { TABLE, CARD }
3    
4    @AuraEnabled
5    public static void log(String type) {
6        try {
7           IsvPartners.AppAnalytics.logCustomInteraction(getInteractionLabel(type)); 
8        } catch (Exception e) {
9            throw new AuraHandledException(e.getMessage());
10        }
11    }
12
13    private static ContactListLayouts getInteractionLabel(String type) {
14        if (type.toLowerCase() == 'table') {
15            return ContactListLayouts.TABLE;
16        } else if (type.toLowerCase() == 'card') {
17            return ContactListLayouts.CARD;
18        } 
19        return null;
20    }
21}

Next, you test your code. With your Apex code debug log level set to FINE, confirm that the custom interactions are logged by finding events in your debug logs called APP_ANALYTICS_FINE, APP_ANALYTICS_WARN, or APP_ANALYTICS_ERROR.

1APP_ANALYTICS_FINE [External]IsvPartners.AppAnalytics.logCustomInteraction was called, but not from an installed managed package.
2This means that the code is ready to be packaged.