<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Noltic - Medium]]></title>
        <description><![CDATA[We deliver Salesforce solutions serving your business exactly as you need it. - Medium]]></description>
        <link>https://medium.com/noltic?source=rss----ff471d048f3a---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Noltic - Medium</title>
            <link>https://medium.com/noltic?source=rss----ff471d048f3a---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 29 May 2026 18:27:42 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/noltic" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Setting up a trigger-based Journey from the Salesforce CRM via REST API — Salesforce Marketing…]]></title>
            <link>https://medium.com/noltic/setting-up-a-trigger-based-journey-from-the-salesforce-crm-via-rest-api-salesforce-marketing-1e0640612087?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/1e0640612087</guid>
            <category><![CDATA[saleforce-marketing-cloud]]></category>
            <category><![CDATA[marketing-cloud]]></category>
            <category><![CDATA[salesforcemarketingcloud]]></category>
            <category><![CDATA[salesforce]]></category>
            <dc:creator><![CDATA[Andrii Demchuk]]></dc:creator>
            <pubDate>Tue, 13 Feb 2024 10:20:05 GMT</pubDate>
            <atom:updated>2024-02-13T10:59:23.183Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>Setting up a trigger-based Journey from the Salesforce CRM via REST API — Salesforce Marketing Cloud tutorial</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*nnyw79_0kWym1uN6" /><figcaption>Photo by <a href="https://unsplash.com/@jack_anstey?utm_source=medium&amp;utm_medium=referral">Jack Anstey</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Some specific project requirements make it necessary to push records for the Journey in SFMC directly from the Salesforce CRM. When the Salesforce Data entry source is not able to cover it as needed, I recommend using REST API callout from the Salesforce CRM.</p><p>Now you have 2 options for how to do it:</p><ul><li>via Flow</li><li>via Apex Trigger</li></ul><p>In this article, you will find detailed instructions on <strong>how to do it usingApex Trigger</strong>.</p><h3>Step 1. Configuring the REST API package.</h3><p>We need to be sure the REST API package is configured properly in the SFMC.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Zm-NyI1amDQIKqeRu9403Q.png" /></figure><blockquote><strong>IMPORTANT</strong>: If you are using several Business Units, you’ll need to provide access to the REST API package for all of them as shown in the screenshot:</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Tfq4JLIgKaJB5hOXVnaOjg.png" /></figure><h3>Step 2. Adding the Data Extension.</h3><p>I recommend building your email template (or other marking content) and adding a <a href="https://help.salesforce.com/s/articleView?language=en_US&amp;id=sf.c360_a_data_extensions.htm&amp;type=5">Data Extension</a> with all of the necessary attributes. As soon as the Data Extension is created, we’ll be able to build the Journey.</p><h3>Step 3. Creating a Journey.</h3><p>We need to select the type of the journey and select the Entry Source (in our case it’s API Event):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/966/0*YzmniIZVRbHHF4vX" /></figure><p>The target Data Extension is the one we created previously.</p><p>Here it is important to understand that in our REST API callout, we will use the <a href="https://developer.salesforce.com/docs/marketing/marketing-cloud/guide/createEventDefinition.html">EVENT DEFINITION KEY</a> from the Journey.</p><p>Add all of the necessary activities to the Journey, then click “Save”, “Validate” and “Activate”.</p><p>When the Journey is created, we can switch to the Salesforce CRM and set up the Apex trigger.</p><h3>Step 4. Setting up the trigger in Apex.</h3><p>First of all, we need to understand when a new record should enter the Journey to select the correct trigger type.</p><p>We need to make 2 different callouts from Apex:</p><ul><li>To take the token</li><li>To trigger the Journey</li></ul><p>Here is a basic example of an Apex Class that you can reuse with your specific adjustments:</p><pre>public with sharing class MC_EmailSendService {<br><br>    public static MARKETING_CLOUD_SETTINGS__c marketingCloudSettings = MARKETING_CLOUD_SETTINGS__c.getOrgDefaults();<br>    public static final String EventDefinitionKey = &#39;SendConfirmationEmail&#39;;<br><br>    public static void sendEventTOSFMC(final String recordId, final String email) {<br>        String token = getToken();<br>        Map&lt;String, String&gt; tokenData = (Map&lt;String,String&gt;) JSON.deserialize(token, Map&lt;String,String&gt;.class);<br>        CalloutWebService.sendRequestMC(<br>                marketingCloudSettings.APP_EVENT_URL__c,<br>                &#39;POST&#39;,<br>                &#39;application/json&#39;,<br>                tokenData.get(&#39;access_token&#39;),<br>                getRequestBodyToSendEvent(recordId, email)<br>        );<br>    }<br><br>    private static String getToken() {<br>        HttpResponse resp = CalloutWebService.sendRequestMC(<br>                marketingCloudSettings.API_TOKEN_URL__c,<br>                &#39;POST&#39;,<br>                &#39;application/json&#39;,<br>                getRequestBody()<br>        );<br>        return resp.getBody();<br>    }<br><br>    private static String getRequestBody() {<br>        JSONGenerator gen = JSON.createGenerator(true);<br>        gen.writeStartObject();<br>        gen.writeStringField(&#39;grant_type&#39;, marketingCloudSettings.GRANT_TYPE__c);<br>        gen.writeStringField(&#39;client_id&#39;, marketingCloudSettings.CLIENT_ID__c);<br>        gen.writeStringField(&#39;client_secret&#39;, marketingCloudSettings.CLIENT_SECRET__c);<br>        gen.writeStringField(&#39;account_id&#39;, marketingCloudSettings.ACCOUNT_ID__c);<br>        gen.writeEndObject();<br>        return gen.getAsString();<br>    }<br><br>    private static String getRequestBodyToSendEvent(final String recordId, final String email) {<br>        return JSON.serialize(new Map&lt;String, Object&gt;{<br>                    &#39;ContactKey&#39; =&gt; recordId,<br>                    &#39;EventDefinitionKey&#39; =&gt; EventDefinitionKey,<br>                    &#39;Data&#39; =&gt; new Map&lt;String, Object&gt;{<br>                            &#39;subscriberKey&#39; =&gt; recordId,<br>                            &#39;email&#39; =&gt; email                    }<br>        });<br>    }<br>}</pre><p>I recommend storing all of the static data for the callouts in the Custom settings or the Named Credentials. In this example, I am using <em>MARKETING_CLOUD_SETTINGS__c</em> for Custom Settings.</p><h3>Step 5. Testing the API connection.</h3><p>To test the REST API callouts, I recommend using <a href="https://www.postman.com/">Postman</a>.</p><h4>1. To get the Token.</h4><p>POST = <a href="https://your_subdomain.auth.marketingcloudapis.com/v2/token">https://<em>YOUR_SUBDOMAIN</em>.auth.marketingcloudapis.com/v2/token</a></p><p><em>YOUR_SUBDOMAIN</em> = <strong>Authentication Base URI</strong> from your REST API package</p><p>Content-Type = application/json</p><p>Body = type <strong>raw</strong></p><pre>{&quot;grant_type&quot;: &quot;client_credentials&quot;,<br>&quot;client_id&quot;: &quot;client_id&quot;,<br>&quot;client_secret&quot;: &quot;client_secret&quot;,<br>&quot;account_id&quot;: &quot;your_MID&quot;<br>}</pre><p><em>client_id</em> = the Client ID value from the REST API package</p><p><em>client_ secret</em> = the Client Secret value from the REST API package</p><p><em>account_id</em> = the MID you can find in your header:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/808/1*L7xbVyBtMsNF-EW-gZdfcA.png" /></figure><blockquote>It is important to define it if you are using multiple Business Units. If you are using just one Business Unit, you can proceed without the account_id.</blockquote><p>Status 200 OK</p><p>Response:</p><pre>{<br>&quot;access_token&quot;: &quot;eyJhbGciOiJIUzI1NiIsImtpZCI6IjQiLCJ2ZXIiOiIxIiwidHlwIjoiSldUIn0.eyJhY2Nlc3NfdG9rZW4iOiJYNUFMU29Mb0Z4b0swZElMSjZDdXBva0YiLCJjbGllbnRfaWQiOiI1dzEyNmRnOGRsOW5wY2x4ZjV4bWlra3oiLCJlaWQiOjUxMDAwNDUxOSwic3RhY2tfa2V5IjoiUzUwIiwicGxhdGZvcm1fdmVyc2lvbiI6MiwiY2xpZW50X3R5cGUiOiJTZXJ2ZXJUb1NlcnZlciIsInBpZCI6NzI3fQ.4iCCytkVPD39z0CjXmZvG_2vZbSd6fUGrMc7Mf4oABg.7DIKoT1qVFnRzT5c9y0Y6nGEIGdRmqEZOraRAAJowKsQ7zEkiwZbLh_ti8Qj9elkUmCYrlpOIFKQ8GaG2FRXaA2STAj89F9qKfJIYw_d9UXNLK2h0BFRwc7fk5qg1FXKlSK2kKjgaF4BLYVnBb1Ds_sguauntZj8QYo6H&quot;,<br>&quot;token_type&quot;: &quot;Bearer&quot;,<br>&quot;expires_in&quot;: 1079,<br>&quot;scope&quot;: &quot;offline documents_and_images_read documents_and_images_write saved_content_read saved_content_write automations_execute automations_read automations_write journeys_execute journeys_read journeys_write email_read email_send email_write push_read push_send push_write sms_read sms_send sms_write social_post social_publish social_read social_write web_publish web_read web_write audiences_read audiences_write list_and_subscribers_read list_and_subscribers_write data_extensions_read data_extensions_write file_locations_read file_locations_write tracking_events_read calendar_read calendar_write campaign_read campaign_write accounts_read accounts_write users_read users_write webhooks_read webhooks_write workflows_write approvals_write tags_write approvals_read tags_read workflows_read ott_chat_messaging_read ott_chat_messaging_send ott_channels_read ott_channels_write marketing_cloud_connect_read marketing_cloud_connect_write marketing_cloud_connect_send event_notification_callback_create event_notification_callback_read event_notification_callback_update event_notification_callback_delete event_notification_subscription_create event_notification_subscription_read event_notification_subscription_update event_notification_subscription_delete tracking_events_write key_manage_view key_manage_rotate key_manage_revoke dfu_configure journeys_aspr journeys_delete package_manager_package package_manager_deploy deep_linking_asset_read deep_linking_asset_write deep_linking_asset_delete deep_linking_settings_read deep_linking_settings_write market_audience_create market_audience_view market_audience_update market_audience_delete market_audience_member_create market_audience_member_view market_audience_member_update market_audience_member_delete contact_bu_mapping_create contact_bu_mapping_view contact_bu_mapping_update contact_bu_mapping_delete http_headers_view http_headers_update http_headers_delete e360_analytics_provisioning_view e360_analytics_provisioning_update e360_analytics_provisioning_delete&quot;,<br>&quot;soap_instance_url&quot;: &quot;https://domain.soap.marketingcloudapis.com/&quot;,<br>&quot;rest_instance_url&quot;: &quot;https://domain.rest.marketingcloudapis.com/&quot;<br>}</pre><p>You need to use <em>access_token</em> in the next callout.</p><blockquote><strong>IMPORTANT</strong>: The token is valid for 20 minutes only.</blockquote><h4>2. To trigger the Journey.</h4><p>POST = <a href="https://your_subdomain.rest.marketingcloudapis.com/interaction/v1/events">https://<em>YOUR_SUBDOMAIN</em>.rest.marketingcloudapis.com/interaction/v1/events</a></p><p><em>YOUR_SUBDOMAIN</em> = <strong>Authentication Base URI</strong> from your REST API Package</p><p>Content-Type = application/json</p><p>Body = type <strong>raw</strong></p><pre>{<br>&quot;ContactKey&quot;: &quot;003…&quot;,<br>&quot;EventDefinitionKey&quot;: &quot;APIEvent-d052ee82-d4e7-…&quot;,<br>&quot;Data&quot;: {<br>&quot;subscriberKey&quot;: &quot;003…&quot;,<br>&quot;email&quot;: &quot;ademchuk@noltic.com&quot;<br>}<br>}</pre><p>EventDefinitionKey = your EVENT DEFINITION KEY from the Journey.</p><p>This target Data Extension contains only 2 fields — <em>subscriberKey</em> and <em>email</em>, but you can add as many as you want based on your business requirements.</p><p>After running the command, a new record should appear in the target Data Extension and the Journey should be triggered as well.</p><p>After your Apex class is finished and you make sure that everything works fine, do not forget to add the Apex test class as well. As a rule of thumb, I recommend adding the Apex test class first.</p><p>That’s it — the records will be pushed to the Journey from the Salesforce CRM automatically now. Let me know if the article was helpful and stay tuned for new Salesforce Marketing Cloud tips and tutorials.</p><p><em>Read our other </em><a href="https://medium.com/noltic"><em>Medium posts</em></a><em> and follow </em><a href="https://noltic.com/?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=journey+trigger+sfmc"><strong><em>Noltic</em></strong></a><em> on </em><a href="https://www.linkedin.com/company/noltic/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.facebook.com/noltic/"><strong><em>Facebook</em></strong></a><em>, and </em><a href="https://twitter.com/realNoltic"><strong><em>Twitter</em></strong></a><em> to stay updated about our news.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1e0640612087" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/setting-up-a-trigger-based-journey-from-the-salesforce-crm-via-rest-api-salesforce-marketing-1e0640612087">Setting up a trigger-based Journey from the Salesforce CRM via REST API — Salesforce Marketing…</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Noltic has released an updated version of a native app for linking and uploading files to…]]></title>
            <link>https://medium.com/noltic/noltic-has-released-an-updated-version-of-a-native-app-for-linking-and-uploading-files-to-e9d2b787367f?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/e9d2b787367f</guid>
            <category><![CDATA[salesforce-productivity]]></category>
            <category><![CDATA[file-upload]]></category>
            <category><![CDATA[salesforce-development]]></category>
            <category><![CDATA[salesforce]]></category>
            <category><![CDATA[appexchange]]></category>
            <dc:creator><![CDATA[Igor Petrovych]]></dc:creator>
            <pubDate>Mon, 08 Jan 2024 23:39:40 GMT</pubDate>
            <atom:updated>2024-01-08T23:40:43.044Z</atom:updated>
            <content:encoded><![CDATA[<h3>Noltic has released an updated version of a native app for linking and uploading files to Salesforce records</h3><p><a href="https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000G12h3UAB&amp;">Cloud File Uploader</a> is an AppExchange product that allows Salesforce file upload from different sources. A solution like this holds great potential for businesses — it helps combine data from various systems, applications, or cloud-based services, providing a comprehensive view of operations and customers.</p><p>When uploading data into Salesforce, Cloud File Uploader also ensures its consistency and accuracy. A solution like that eliminates the risk of working with outdated or duplicated files by synchronizing information across different sources. This helps businesses maintain a single version of the truth, enhancing decision-making and avoiding confusion or misunderstandings caused by conflicting data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DwahIV-nl_-2x9b9" /><figcaption>Cloud File Uploader screen to select upload source</figcaption></figure><p>Businesses running on Salesforce usually have at least one of two problems:</p><ol><li>How to upload files to Salesforce from multiple sources?</li><li>How to link files stored outside of Salesforce to the records in the system?</li></ol><p>Cloud File Uploader solves both of those problems. It allows uploading files from multiple sources to Salesforce or external storage with the ability to link them to Salesforce records.</p><p>The ability to link files from different sources that comes with Cloud File Uploader allows for saving Salesforce file storage. It also promotes efficient collaboration across teams and departments that use different platforms — they can easily share, access, and work on files regardless of their initial source or location. This eliminates the need for manual file transfers, reducing errors and saving time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*vUz57rkkiCdGXvPd" /><figcaption>Photo by <a href="https://unsplash.com/@nasa?utm_source=medium&amp;utm_medium=referral">NASA</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p><strong>What’s New</strong></p><p>In the new version of Cloud File Uploader, the API has been updated to make the process of uploading files to external storage faster and more secure. We use the Uploadcare platform to store files. The configuration of Uploadcare allows the files to be alternatively stored on S3. To allow users to view and manage their remote files from Salesforce, we provide the functionality that uses the link to file preview, and a new API allows users to delete files from the cloud from Salesforce.</p><p><strong>Full list of features &amp; functionality</strong></p><ul><li>Native Salesforce solution</li><li>Upload files into Salesforce from 12 different sources, including all the popular cloud storage providers (Facebook, Google Drive, Google Photos, Dropbox, Instagram, Evernote, Flickr, OneDrive, Box, Huddle)</li><li>A no-code solution to store locally in Salesforce linked to Salesforce records</li><li>Native Salesforce Lightning file uploader for local files, allowing you to upload files up to 2GB</li><li>Secure file upload to Salesforce from remote URLs</li><li>No-code solution to store files remotely on the Uploadcare platform (requires an Uploadcare account) and S3 (through Uploadcare)</li></ul><p><em>“With the new release, the ability to store files outside of Salesforce, while leveraging the ability to link those files to records in Salesforce will allow to use Salesforce storage more effectively, and not hog it with the file storage,”</em> says Igor Petrovych, CEO at Noltic</p><p>We keep our app up-to-date to incorporate bug fixes and other improvements per client requests. Among the latest features planned to be released is the migration of files from the local storage to a remote location, while maintaining links to records. This will allow Salesforce users of existing orgs to adapt our app very quickly.</p><p><a href="https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000G12h3UAB&amp;">Start using Cloud File Uploader for free now.</a></p><p><em>Read our other </em><a href="https://medium.com/noltic"><em>Medium posts</em></a><em> and follow </em><a href="https://noltic.com?utm_source=medium&amp;utm_medium=article&amp;utm_campaign=cfu+release"><em>Noltic</em></a><em> on </em><a href="https://www.linkedin.com/company/noltic/"><em>LinkedIn</em></a><em>, </em><a href="https://www.facebook.com/noltic/"><em>Facebook</em></a><em>, and </em><a href="https://twitter.com/realNoltic"><em>Twitter</em></a><em> to stay updated about our news.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e9d2b787367f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/noltic-has-released-an-updated-version-of-a-native-app-for-linking-and-uploading-files-to-e9d2b787367f">Noltic has released an updated version of a native app for linking and uploading files to…</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Marketing Cloud Personalization Triggered Campaigns: Personalized emails with dynamically…]]></title>
            <link>https://medium.com/noltic/salesforce-marketing-cloud-triggered-campaigns-personalized-emails-with-dynamically-recommended-3d43fd955e1c?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/3d43fd955e1c</guid>
            <category><![CDATA[marketing-cloud]]></category>
            <category><![CDATA[salesforce]]></category>
            <category><![CDATA[marketing-automation]]></category>
            <category><![CDATA[salesforcemarketingcloud]]></category>
            <dc:creator><![CDATA[Andrii Demchuk]]></dc:creator>
            <pubDate>Tue, 05 Dec 2023 09:35:42 GMT</pubDate>
            <atom:updated>2023-12-06T10:25:00.183Z</atom:updated>
            <content:encoded><![CDATA[<h3>Marketing Cloud Personalization Triggered Campaigns: Personalized emails with dynamically recommended content</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*eZMw5YrHVxZ0CTdQ" /><figcaption>Photo by <a href="https://unsplash.com/@priscilladupreez?utm_source=medium&amp;utm_medium=referral">Priscilla Du Preez 🇨🇦</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Salesforce Marketing Cloud Personalization opens up a whole multiverse of communication journeys tailored to specific customer lifecycles. It provides a level of targeted content delivery hardly ever seen before and helps build strong customer-oriented strategies.</p><p>The most popular application of SFMC customization abilities is email marketing with triggered campaigns. Using this guide, you’ll be able to configure dynamically personalized recommendation blocks for customers you want to engage with over email.</p><h3>Step 1.</h3><p>Define recipes you will use in the Campaign configuration or Server-Side Triggered Templates to provide recommendations based on some specific parameters depending on your business needs.</p><h3>Step 2.</h3><p>Create a Server-Side Triggered Template in Personalization. It is the Server-side Code that allows you to define custom logic as well.</p><p>In the Journey Builder Trigger global template, go to the JourneyBuilderTriggeredPayload class. There, you will need to define your recommendations and user Attributes.</p><h3>Step 3.</h3><p>Create a target Data Extension in Marketing Cloud. That specific Data Extension should contain the user Attribute defined in the Server-Side Triggered Template in Personalization. Data Extension should be sendable.</p><p>Create a field for each user attribute in the event data extension in Salesforce Marketing Cloud. Data extension field names must match user attribute names.</p><p>After you select a recipe, create a Recommendations field in the event data extension in Marketing Cloud. Doing so allows you to add a Recommendations block to an email in Marketing Cloud.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/830/0*fyu7BI62AiQPoTsL" /></figure><h3>Step 4.</h3><p>Create a Server-Side Campaign. Here you need to define some specifics to ensure you can set up triggers via REST API.</p><h4>Campaign Targeting:</h4><ul><li>Channel contains Server (default one, recommended to keep it as it is);</li><li>Add rule &gt; Action includes Get Recommendation (name of your new purposely created or already existing Event).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/642/0*-u4BCt-Gg7nwQwgo" /></figure><h4>Experience:</h4><ul><li>Select the target Server-Side Triggered Template;</li><li>User Attributes (one of the identity types) — in our case, I am using emailAddress;</li><li>In the Email Recommendations section, you need to define the previously created recipes.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/368/0*ilXxqZymSl6CmHyT" /></figure><p>As a result, your Server-Side Campaign should look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/379/0*8oIvJLnFYfyVZJ3c" /></figure><p>Save and publish it.</p><h3>Step 5.</h3><p>Create a code snippet for our email template to send the event to Personalization and get our fresh recommendations from the Server-Side Campaign. The Content will be changed dynamically based on the selected record from the target Data Extension and the result of the Recipe calculation.</p><p>You’ll need to make a REST API callout to get the recommendation (I’m using SSJS):</p><pre>var emailAddress = Attribute.GetValue(‘Email’);<br>var payload = &#39;{&quot;user&quot;: {&quot;attributes&quot;: {&quot;emailAddress&quot;: &#39; + &#39;&quot;&#39; + emailAddress + &#39;&quot;&#39; + &#39;}},&quot;source&quot;: {&quot;channel&quot;: &quot;Server&quot;},&quot;interaction&quot; : {&quot;name&quot;: &quot;Get Recommendations&quot;}}&#39;;<br>var req = new Script.Util.HttpRequest<br>(https://&lt;accountName&gt;.&lt;instance&gt;.evergage.com/api2/authevent/&lt;dataset&gt;&#39;);<br>req.emptyContentHandling = 0;<br>req.retries = 2;<br>req.continueOnError = true;<br>req.contentType = &quot;application/json&quot;<br>req.setHeader(&quot;Authorization&quot;, &#39;Basic {code*}&#39;);<br>req.method = &quot;POST&quot;;<br>req.postData = payload;<br>var resp = req.send();<br><br>//* You need to encode {API Key ID,&quot;API Key Secret&quot;} to Base64 format</pre><h3>Step 6.</h3><p>Parse the response based on your configurations in the email template, in my case, it looks like this:</p><pre>var respPayload = Platform.Function.ParseJSON(String(resp.content));<br>var recommendations = respPayload.campaignResponses[0].payload.Recommendations;<br>var Catalog_Data = Platform.Function.ParseJSON(recommendations);</pre><p>I have the result of the REST API Callout saved in the variable <em>Catalog_Data.</em> You need to define the HTML body to preview the recommendation based on your business needs:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/830/0*MoIswO603gomIVhm" /></figure><p>This <a href="https://help.salesforce.com/s/articleView?id=sf.mc_pers_triggered_campaign_email_code_samples.htm&amp;type=5">documentation article</a> should be of help during the implementation.</p><h3>Step 7.</h3><p>Create a Journey to send emails regularly and schedule them correctly (daily/hourly/weekly/monthly/yearly):</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/711/0*pzV07abGNK_MmcBG" /></figure><p>As an Entry Source for the Journey, I am using the Data Extension created in Step 3.</p><p>Save, Validate, and Activate your Journey. There you have it!</p><p><em>Read our other </em><a href="https://medium.com/noltic"><em>Medium posts</em></a><em> and follow </em><a href="https://noltic.com/?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=personalized+emails"><strong><em>Noltic</em></strong></a><em> on </em><a href="https://www.linkedin.com/company/noltic/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.facebook.com/noltic/"><strong><em>Facebook</em></strong></a><em>, and </em><a href="https://twitter.com/realNoltic"><strong><em>Twitter</em></strong></a><em> to stay updated about our news.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3d43fd955e1c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/salesforce-marketing-cloud-triggered-campaigns-personalized-emails-with-dynamically-recommended-3d43fd955e1c">Marketing Cloud Personalization Triggered Campaigns: Personalized emails with dynamically…</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to get Session ID for Salesforce managed packages]]></title>
            <link>https://medium.com/noltic/how-to-get-session-id-for-salesforce-managed-packages-533c1a654549?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/533c1a654549</guid>
            <category><![CDATA[appexchange]]></category>
            <category><![CDATA[salesforce]]></category>
            <category><![CDATA[salesforce-development]]></category>
            <dc:creator><![CDATA[Oleksandr Putria]]></dc:creator>
            <pubDate>Fri, 29 Sep 2023 10:50:27 GMT</pubDate>
            <atom:updated>2023-09-29T11:06:54.354Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YPyH42RVU7RnPwqR" /><figcaption>Photo by <a href="https://unsplash.com/@markusspiske?utm_source=medium&amp;utm_medium=referral">Markus Spiske</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Salesforce Session ID is a crucial piece of authentication and security information used in the Salesforce platform. It is a unique identifier generated by Salesforce when a user logs in and represents an active user session. The Session ID is used to authenticate and authorize a user’s access to Salesforce resources, such as data, APIs, and user interfaces.</p><p>Developers often use Session ID when making API calls to Salesforce. The Session ID parameter is included in the HTTP headers of API requests as a form of authentication. This allows external applications and services to interact with Salesforce on behalf of a user without requiring them to log in each time.</p><p>Salesforce offers a security review process for applications developed on the platform. This review helps ensure that your application complies with Salesforce’s security policies and best practices of data safety.</p><p>During the security review, Salesforce evaluates how your application handles sensitive data, including Session IDs, and checks for vulnerabilities and security flaws.</p><p>Today I am going to invite you to go with me through the way I went to get Session ID for <a href="https://noltic.com/our-products?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=sessionid">our company’s managed packages</a>. To see the pitfalls we’ve met and what we found out.</p><h3><strong>The approaches to obtaining Session ID</strong></h3><p>When you’re looking to integrate with a web service or utilize Apex-MDapi, acquiring a Session ID is a key step, as it serves as your Bearer token for authentication purposes. Getting a Session ID can be accomplished through various methods, readily available with a quick online search.</p><p>The simplest one is</p><pre>UserInfo.getSessionId();</pre><p>When executing it within an anonymous window, the initial challenge you’ll encounter is the inability to view it in the debug log. In most cases, you’ll likely come across an output similar to the following:</p><pre>|USER_DEBUG|[14]|DEBUG|SESSION_ID_REMOVED</pre><p>There are a few workarounds to obtain the Session ID value:</p><p>Create a new Case record and save the Session ID in the description field. You can then retrieve it from the standard Salesforce user interface.</p><pre>Case c = new Case(Description = UserInfo.getSessionId());</pre><p>Execute this code snippet, retrieve the result, and then remove any whitespace.</p><pre>UserInfo.getOrganizationId().substring(0, 15) + ‘ ‘ + UserInfo.getSessionId().substring(15)</pre><p>To proceed with making a request, the next step involves retrieving the organization URL in an external format. You can quickly obtain it using the following code snippet:</p><pre>URL.getOrgDomainUrl().toExternalForm();</pre><p>With the Session ID and Organization URL in hand, you can leverage tools like <a href="https://www.postman.com/">Postman</a> along with <a href="https://github.com/forcedotcom/postman-salesforce-apis">Salesforce Collections</a> or simply use the <a href="https://www.postman.com/salesforce-developers/workspace/salesforce-developers/overview">Postman Salesforce Workspace</a> to interact with the API and validate the functionality of your Session ID, also known as the token.</p><p><strong>In the screenshot below, you’ll find an example illustrating the retrieval of Organization Limits.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-dAPJ09WQroevsYV" /></figure><p>Now, everything appears to be in order, and it seems like we can utilize it for our solutions. But there’s always a ‘but’. What if we attempt to use it with our Lightning Web Component? So let’s create a straightforward LWC component with a button and its corresponding Apex controller.</p><pre>public with sharing class SessionIdController {<br><br>@AuraEnabled<br> public static String getLimits() {<br> String endpoint = Url.getOrgDomainUrl().toExternalForm() + &#39;/services/data/v58.0/limits&#39;;<br> String bearer = &#39;Bearer &#39; + UserInfo.getSessionId();<br><br>HttpRequest req = new HttpRequest();<br> req.setEndpoint(endpoint);<br> req.setMethod(&#39;GET&#39;);<br> req.setHeader(&#39;Authorization&#39;, bearer);<br><br>Http http = new Http();<br> HttpResponse res = http.send(req);<br> return res.getBody();<br> }<br>}</pre><p>When we attempt to do this from the LWC component, an error will occur, and the response will resemble what’s shown in the screenshot below:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9us_Y8A9MOpqvv_a" /></figure><p>Executing the same controller’s method in an anonymous window returns the expected response:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*nCc291yeFgkOIxy4" /></figure><h3><strong>Visualforce page approach</strong></h3><p>In Salesforce, you don’t need to explicitly obtain the Session ID when working with Visualforce pages because the Session ID is automatically available within the context of a Visualforce page. Salesforce handles the authentication and session management for you.</p><pre>&lt;! — SessionIdPage →<br>&lt;apex:page contentType=”application/json”&gt;<br> {“sessionId”:”{!$Api.Session_ID}”}<br>&lt;/apex:page&gt;</pre><p>In the example above, the <em>{$Api.Session_ID}</em> expression is used to display the Session ID on the Visualforce page. Salesforce automatically provides this value, and you can access it directly.</p><p>So we can use this method to retrieve the Session ID from a Visualforce page. The most prevalent approach to acquire the Session ID securely is by creating a Visualforce page and incorporating a global merge field to extract it from the page.</p><pre>public class SessionIdService {<br><br>public class SessionWrapper {<br> public string sessionId;<br> }<br> @AuraEnabled<br> public static string getSessionId() {<br> SessionWrapper wrapper = (SessionWrapper) JSON.deserialize(<br> Page.SessionIdPage.getContent().toString(),<br> SessionWrapper.class<br> );<br> return wrapper.sessionId;<br> }<br>}</pre><p>Since this approach works as intended, many developers continue to use it successfully. However, when it comes to incorporating it within a managed package, several considerations and challenges arise.</p><h3><strong>Session ID, Managed Packages and Security Review</strong></h3><p>In Salesforce, they really value the trust of their customers. If you’re an independent software vendor (ISV) and want to share your managed package with the public, it has to go through a security review to make sure it’s safe.</p><p>We had some doubts about using the Visualforce approach in managed packages. It seemed more like a workaround than an solid solution. So, we set up a meeting with Salesforce Support to talk about our needs and figure out how to do it the right way, following all the security rules.</p><p>At Noltic, while creating our managed packages like <a href="https://noltic.com/checkmynumber?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=sessionid">CheckMyNumber</a> and <a href="https://noltic.com/tracky?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=sessionid">Tracky</a>, we had some peculiar situations. We needed to connect our web services to give users a better experience. To do this, we used something called <a href="https://github.com/certinia/apex-mdapi">Apex-Mdapi</a> as a part of our solution.</p><h3><strong>Canvas Connected Application</strong></h3><p>Canvas enables you to integrate a third-party application in Salesforce easily. Canvas is a set of tools and JavaScript APIs that you can use to expose an application as a canvas app. This means you can take your new or existing applications and make them available to your users as part of their Salesforce experience.</p><p>When you use a signed request for authentication in your canvas app, you receive a CanvasRequest object in the initial POST message from Salesforce. This object contains a lot of information about the Client and Context. The Client object has an oauth token so all other aspects we can handle from the service side.</p><p>There are some steps in order to create a Canvas Connected Application:</p><ul><li>Callback URL is a required field, as we don’t use it and can’t leave it empty we can put in some dummy URL</li><li>In the Canvas Setting section, we need to specify our web service URL and select Access Method: Signed Request (POST)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*frSFtFqU-12PoDoK" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/894/0*-425fN_P438BSxwb" /></figure><p><strong>We’ve achieved successful integration using Canvas for our </strong><a href="https://noltic.com/checkmynumber?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=sessionid"><strong>CheckMyNumber</strong></a><strong> application.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CEPpUWKSgIThG8H4" /></figure><h4><strong>Connected Application for Apex-Mdapi</strong></h4><p>In our products, we had specific processes to implement, and we chose <a href="https://github.com/certinia/apex-mdapi">Apex-Mdapi</a> for this purpose. Following Salesforce’s guidance, we explored authentication options for connected apps and selected OAuth 2.0 JWT Bearer Flow for Server-to-Server due to its lack of user interaction. The central idea is to utilize a connected app as a token provider, include it in the managed package, and use it in subscriber organizations.</p><p><strong>The first step is generating a certificate</strong></p><pre># Generate an RSA private key<br>openssl genrsa -des3 -passout pass:x -out server.pass.key 2048<br><br># Create a key file from the server.pass.key file<br>openssl rsa -passin pass:x -in server.pass.key -out server.key<br><br># Request and generate the certificate<br>openssl req -new -key server.key -out server.csr<br><br># Generate the SSL certificate<br>openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt</pre><p><strong>Afterwards, we need to create a connected app</strong></p><p>Then do these steps:</p><ul><li>Go to <strong>Setup</strong> &gt; <strong>Connected</strong> <strong>app</strong> &gt; <strong>New</strong>.</li><li>Fill in Name and Email</li><li>Click on ‘Enable OAuth Setting’</li><li>Call back URL ‘https://login.salesforce.com’</li><li>Click on ‘Use Digital Signature’ and upload the certificate created.</li><li>Select the following OAuth Scopes — Manage user data via APIs (api), Perform requests at any time (refresh_token, offline_access)</li><li>Click on ‘Save’</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GRTuX08YtRqt8aOY" /></figure><h4><strong>JWT Flow Using Apex</strong></h4><p>We’ve set up the connected app, and we can finally use Apex code to obtain the access token.</p><p>There is some data that you need in order to perform the request.</p><p>Headers:</p><pre>{“alg”:”RS256&quot;}</pre><p>Payload: Data</p><pre>{<br> “iss” : “Connected App Consumer Key”,<br> “sub”: “CurrentUserName”,<br> “aud”: “https://login.salesforce.com&quot; or “https://test.salesforce.com&quot;,<br> “exp”: now + 5minutes<br>}</pre><p>Then your request should look like this:</p><p><strong>Method: </strong>POST</p><p><strong>URL: </strong><a href="https://login.salesforce.com/services/oauth2/token">https://login.salesforce.com/services/oauth2/token</a> or <a href="https://login.salesforce.com/services/oauth2/token">https://test.salesforce.com/services/oauth2/token</a> (scratch org or sandbox)</p><p><strong>Headers: </strong>‘Content-type’, ‘application/x-www-form-urlencoded’</p><p><strong>Body</strong>:</p><ul><li>grand_type : urn:ietf:params:oauth:grant-type</li><li>assertion : JWT TOKEN</li></ul><p>With the code below we can generate a JWT and make a call to acquire a Salesforce access token. Don’t forget to add <a href="http://login.salesforce.com/">login.salesforce.com</a> and <a href="http://test.salesforce.com/">test.salesforce.com</a> to your remote site settings as we’ll be using them as endpoints.</p><pre>public String base64UrlEncode(Blob input){<br> String output = EncodingUtil.base64Encode(input);<br> output = output.replace(‘+’, ‘-’);<br> output = output.replace(‘/’, ‘_’);<br> while ( output.endsWith(‘=’)){<br> output = output.substring(0,output.length()-1);<br> }<br> return output;<br> }<br> <br> String getJWT(<br> String iss, <br> String sub, <br> String aud, <br> String privateKey) <br> {<br> String encodedHeader = base64UrlEncode(<br> Blob.valueOf(<br> JSON.serialize(new Map&lt;String, String&gt; {‘alg’ =&gt; ‘RS256’})<br> )<br> );<br><br>String encodedBody = base64UrlEncode(<br> Blob.valueOf(<br> JSON.serialize(new Map&lt;String, Object&gt; {<br> &#39;iss&#39; =&gt; iss,<br> &#39;sub&#39; =&gt; sub,<br> &#39;aud&#39; =&gt; aud,<br> &#39;exp&#39; =&gt; Datetime.now().getTime()/1000 + 300<br> })<br> )<br> );<br><br> String jwt = encodedHeader + &#39;.&#39; + encodedBody;<br> Blob signature = Crypto.sign(<br> &#39;rsa-sha256&#39;,<br> Blob.valueOf(jwt),<br> EncodingUtil.base64Decode(privateKey)<br> );<br><br> jwt += &#39;.&#39; + base64UrlEncode(signature);<br> return jwt;<br> }</pre><p>There are only a couple of steps left to do. Or rather, there are only manual steps left that our subscribers need to do after the installation of our 1GP manage packages:</p><h4><strong>Set up Permitted users to ‘Admin approved users are pre-authorized’</strong></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*QNsuTDaFt6KcMLzY" /></figure><h4><strong>Add profiles that are supposed to use your connected app</strong></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1mH92WRxVTcpittD" /></figure><p>In conclusion, the Salesforce Session ID is a vital component for authentication and security within the Salesforce platform. It serves as a unique identifier representing an active user session and is essential for accessing Salesforce resources, making API calls, and interacting with the platform on behalf of users.</p><p>Obtaining the Session ID can be achieved through various methods. However, when working with managed packages and security considerations, developers should carefully evaluate their approach.</p><p>It’s essential to follow Salesforce’s security guidelines and consider the specific needs of your application when choosing the most appropriate method for obtaining and utilizing the Session ID.</p><p>This is Noltic’s approach for 1gp-managed packages and Session ID, I really hope it helps others working with Salesforce.</p><p><em>Read our other </em><a href="https://medium.com/noltic"><em>Medium posts</em></a><em> and follow </em><a href="https://noltic.com/?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=sessionid"><strong><em>Noltic</em></strong></a><em> on </em><a href="https://www.linkedin.com/company/noltic/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.facebook.com/noltic/"><strong><em>Facebook</em></strong></a><em>, and </em><a href="https://twitter.com/realNoltic"><strong><em>Twitter</em></strong></a><em> to stay updated about our news.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=533c1a654549" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/how-to-get-session-id-for-salesforce-managed-packages-533c1a654549">How to get Session ID for Salesforce managed packages</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Matching the sender with the recipient: Dynamic Sender profile and Reply Mail Management in SFMC]]></title>
            <link>https://medium.com/noltic/matching-the-sender-with-the-recipient-dynamic-sender-profile-and-reply-mail-management-in-sfmc-ec8a8e3c7f4a?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/ec8a8e3c7f4a</guid>
            <category><![CDATA[marketing-automation]]></category>
            <category><![CDATA[marketing-cloud]]></category>
            <category><![CDATA[email-marketing]]></category>
            <dc:creator><![CDATA[Andrii Demchuk]]></dc:creator>
            <pubDate>Tue, 26 Sep 2023 13:07:06 GMT</pubDate>
            <atom:updated>2023-09-26T14:15:50.297Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pKXoTr5WrqFqb_HQMVa61w.jpeg" /></figure><p>In Salesforce Marketing Cloud, a Sender profile is a necessary attribute for message distribution. It is the person included in the ‘From’ section of the message and is the main corporate communication representative for the client.</p><p>To personalize the customer experience, a marketer or whoever manages the communication with the clients can choose dynamic contact data to include in the ‘From’ field of their message. This is quite useful in cases of previous personal communication between a specific customer and their CS representative or account owner.</p><p>Marketing Cloud allows for creating a dynamic Sender profile to dynamically match each customer with a corresponding contact person’s details. If a customer decides to reply, their response will also be sent to the person in the initial email ‘From’ field. Let’s see how it’s done.</p><p><strong>How to create a dynamic Sender profile</strong></p><p>1. To create a Data Extension Sender profile, you must have 2 fields in data extension: From_Name and From_Email.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wKHMnipk2wSGnfd8P0wjVA.png" /></figure><p>2. After, you must have 2 Code Snippets — ‘Dynamic From Email’ and ‘Dynamic From Name’.</p><p>Sample AMPScript to put into the Code Snippet Content Block which assumes the source for the send has an attribute in the target Data Extension titled ‘From_Name’:</p><pre>%%[<br>VAR @fromName<br>SET @fromName = [From_Name]<br>]%%</pre><p>Create a separate code snippet for an attribute in the target Data Extension titled ‘From_Email’.</p><pre>%%[<br>VAR @fromEmail<br>SET @fromEmail = [From_Email]<br>]%%</pre><p>3. After that, we go to Setup &gt; Feature Settings &gt;Email Studio &gt; Sender Profiles.</p><p>We choose ‘Dynamic SP’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*K5uV8PAqjDLbHbel" /></figure><p>4. Fill out the Sender Profile From Name and From Email fields:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ZuPr28RdpmdClUKl" /></figure><p>After ‘ContentBlockByKey’ should be the key for our code snippets, which we created early.</p><p>To get our Code Snippet, we must open our Code Snippets and copy the Customer Key. The format should look like this:</p><pre>%%=ContentBlockByKey(“CustomerKey”) =%%</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EM19KcFKUHNA6-zX" /></figure><p>After that, click ‘Save’ in the Sender Profile.</p><p>5. Now, when sending emails, select ‘Dynamic SP’ in the Sender Profile. All done!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PMudUiS9QN4NwB_b" /></figure><p><strong>How to use Reply Mail Management</strong></p><p>After mastering the dynamic Sender profile, we should set up a scenario for a customer’s reply. When responding to a dynamically sent email, the response should be sent immediately to the user from whom the initial email was sent.</p><p>To use the ‘Reply Mail Management’ feature, you need to have 2 fields in data extension: Reply_Name and Reply_Email.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CejubHDIjn2cS_xC9BcHug.png" /></figure><p>Go to Setup &gt; Feature Settings &gt; Email Studio &gt; Reply Mail Management. Go to ‘Populate Reply-to Address Dynamically’. Now, put <em>%%Reply_Name%% </em>in ‘Reply Name’, and in Reply Email — <em>%%Reply_Email%%</em>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/833/0*8zTHp8IOs37on1L9" /></figure><p>That’s it, now the customers will be receiving their emails from a familiar account, and their replies will be handled by the best suitable team member!</p><p><em>Read our other </em><a href="https://medium.com/noltic"><em>Medium posts</em></a><em> and follow </em><a href="https://noltic.com/?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=dynamic+sender+profile"><strong><em>Noltic</em></strong></a><em> on </em><a href="https://www.linkedin.com/company/noltic/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.facebook.com/noltic/"><strong><em>Facebook</em></strong></a><em>, and </em><a href="https://twitter.com/realNoltic"><strong><em>Twitter</em></strong></a><em> to stay updated about our news.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ec8a8e3c7f4a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/matching-the-sender-with-the-recipient-dynamic-sender-profile-and-reply-mail-management-in-sfmc-ec8a8e3c7f4a">Matching the sender with the recipient: Dynamic Sender profile and Reply Mail Management in SFMC</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Update All Subscribers — Salesforce Marketing Cloud Data Sync with Sales Cloud]]></title>
            <link>https://medium.com/noltic/update-all-subscribers-salesforce-marketing-cloud-data-sync-with-sales-cloud-f1c6e28403a6?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/f1c6e28403a6</guid>
            <category><![CDATA[marketing-cloud]]></category>
            <category><![CDATA[salesforce-development]]></category>
            <category><![CDATA[marketing-automation]]></category>
            <category><![CDATA[salesforce]]></category>
            <dc:creator><![CDATA[Andrii Demchuk]]></dc:creator>
            <pubDate>Thu, 07 Sep 2023 14:10:25 GMT</pubDate>
            <atom:updated>2023-09-08T12:43:08.518Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>Update All Subscribers — Salesforce Marketing Cloud Data Sync with Sales Cloud</strong></h3><p>Synchronizing Subscriber data between Salesforce Sales Cloud and Marketing Cloud is not only used to literally extract the data from one place and put it into the other. It’s also a great opportunity to perform a simultaneous validity check of the contact base in the CRM.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*lkVY1gU93XndTq79" /></figure><p>To update the Subscribers data in the Marketing Cloud Data Extension and get a list of failed attempts often caused by the emails being invalid, we’ll need to follow these steps:</p><ol><li>Create Data Extension</li><li>Automation: Get Records from SFDC</li><li>Automation: Extract All Subscribers</li><li>Automation: Export All Subscribers</li><li>Automation: Update All Subscribers</li></ol><p>Also, to get started, we need to create an FTP Account (file transfer protocol account) for transferring files with a host computer using FTP services, which we will use in the Automation process. To do this, go to Setup &gt; Administration &gt; Data Management &gt; FTP Accounts. Then, in FTP Accounts, click on ‘Create User’.</p><h3><strong>Create Data Extension</strong></h3><p>Let’s create a Data Extension with the necessary fields and name it ‘All Subscribers Data’. For example, we can create a Data Extension with three fields:</p><ul><li>Subscriber Key;</li><li>Status (subscription status);</li><li>Email Address (subscriber email).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/946/0*MMiw1VR7MMbjBg0I" /></figure><p>We will store our data about subscribers in it, including their email address and subscription status from Sales Cloud.</p><h3><strong>Automation: Get Record From SFDC</strong></h3><p>Next, navigate to the Automation Studio in Journey Builder and create a new automation named ‘Update All Subscribers’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/208/0*RSytrT72bhZxiyA-" /></figure><p>Next, let’s go to the workflow, where we can see all the activities that we can add to the automation. Choose the ‘SQL Query’ activity and drag it to the right on Canvas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aJdvUFrnNOfFNtrB" /></figure><p>In the Choose SQL Query Activity section, click ‘Create New Query Activity’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ZB1azPSjBr-Ed8U-" /></figure><p>Enter the name of the Query Activity as ‘Get Records from SFDC’. In the Folder Location, select the folder where the query will be saved. Then, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0W34vBUHoN-XJuJp" /></figure><p>In the QUERY step, enter the following SQL query to retrieve saved data about subscribers from Sales Cloud in Data Extension.</p><pre>SELECT<br>sfdc.Id as [Subscriber Key],<br>sfdc.Email as [Email Address],<br>CASE<br>WHEN sfdc.HasOptedOutOfEmail = &#39;FALSE&#39; THEN &#39;active&#39; ELSE &#39;unsubscribe&#39; <br>END AS Status<br>FROM<br>[Lead_Salesforce] as sfdc<br>WHERE<br>sfdc.Email IS NOT NULL<br>AND<br>sfdc.HasOptedOutOfEmail IS NOT NULL<br>UNION<br>SELECT<br>sfdc1.Id as [Subscriber Key],<br>sfdc1.Email as [Email Address],<br>CASE<br>WHEN sfdc1.HasOptedOutOfEmail = &#39;FALSE&#39; THEN &#39;active&#39; ELSE &#39;unsubscribe&#39; <br>END AS Status<br>FROM<br>[Contact_Salesforce] as sfdc1<br>WHERE<br>sfdc1.Email IS NOT NULL<br>AND<br>sfdc1.HasOptedOutOfEmail IS NOT NULL</pre><p>We have saved subscribers’ data from both Lead and Contact objects in Sales Cloud. In the Data Extension, the field Status corresponds to ‘HasOptedOutOfEmail’ in Sales Cloud. If the value of ‘HasOptedOutOfEmail’ is ‘False’, the Status is considered ‘Active’; otherwise, it is considered ‘Unsubscribed’.</p><p>Then, click ‘Next’.</p><p>In Data Extensions, select ‘All Subscribers Data’, which we have created. In the Data Action choose ‘Update’ to ensure the data isn’t overwritten and is constantly updated. Then, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_pci7K7jW-zjbBQj" /></figure><p>In summary, check the input data and click ‘Finish’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0Chlr_KyCW0mi8jb" /></figure><h3><strong>Automation: Extract All Subscribers</strong></h3><p>Select the ‘Data Extract’ activity and drag it to the right on the Canvas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/644/0*HKno1_Ji1wmLvb--" /></figure><p>After clicking ‘Create New Data Extract Activity’, click ‘Choose’ in Data Extract.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*wXOgP02_WGBHLVR1" /></figure><p>In Properties, enter ‘Extract All Subscribers’ in the ‘Name’ field. For the ‘File Naming Pattern’, provide a file name, for example, ‘ImportAllSub’. In the ‘Extract Type’ field, select ‘Data Extension Extract’. Then, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1jq_pbwjQRx2G-4v" /></figure><p>In the Configuration section, select ‘Has Column Headers’ and enter a ‘,’ (comma) in the Column Delimiter field. For the DECustomer Key, enter the External Key Data Extension we created earlier. Then, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9wYCFZ6gYxDZHbHr" /></figure><p>In summary, check the input data and click ‘Finish’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*d5dVrxtO7cGXgPRb" /></figure><h3><strong>Automation: Export All Subscribers</strong></h3><p>Select the ‘File Transfer’ activity and drag it to the right on the Canvas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/984/0*YCYAzq50e8xsEyFm" /></figure><p>After clicking ‘Create New File Transfer Activity’, click ‘Choose’ in File Transfer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*dRpcOOa96MWaw902" /></figure><p>In the Properties section, fill in the Name field with ‘Export All Subscribers’. Choose ‘Move a File From Safehouse’ as the File Action, then click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*TxREKPGxxRRyqf0-" /></figure><p>In the Configuration section, input ‘ImportAllSub’ into the File Naming Pattern field, which refers to the same file created during the ‘Data Extract’ step. For the ‘Destination’, select ‘ExactTarget Enhanced FTP’, and then proceed by clicking ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DaMGxFHOpzyfmXEP" /></figure><p>In summary, check the input data and click ‘Finish’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*immrYAuzJvD6Bk12" /></figure><h3><strong>Automation: Update All Subscribers</strong></h3><p>Select the ‘Import File’ activity and drag it to the right on the Canvas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EmoJR9KfVRFXcbf9" /></figure><p>Click ‘Choose’ in the Import File, after clicking ‘Create New Import Definition’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*5vh_k29StAU4Bvkw" /></figure><p>In the Properties section, enter ‘Update All Subscribers’ in the ‘Name’ field. If you want to receive emails with this data in .txt format, select ‘Send notification email to:’ and provide your email address.</p><p>Finally, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*wQTdEpiyT_RAntM_" /></figure><p>In the Import File section, select ‘ExactTarget Enhanced FTP’ as the File Location.</p><p>Enter ‘ImportAllSub’ in the File Naming Pattern field. On the right-hand side, in the ‘Delimiter’ section, choose ‘Comma’. Make sure to unselect ‘Respect double quotes(“) as a text delimiter’.</p><p>Finally, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*r8SKhKCLd6HMZ1c2" /></figure><p>In the Destination section, choose ‘Subscriber List’. Then, click on the folder named ‘my subscribers’ and select ‘All Subscribers’. Finally, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*k215tTOIpPa-Lzr5" /></figure><p>In the Mapping section, select ‘Add and Update’ and click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*iSo8W2GiCjSFshX0" /></figure><p>In the Review section, check the input data and click ‘Finish’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*SCuCKLvwstekwXSY" /></figure><p>After completing the previous steps, you can schedule this automation to run every hour. This ensures that the data in Marketing Cloud is continuously updated with Sales Cloud.</p><p><em>Read our other </em><a href="https://medium.com/noltic"><em>Medium posts</em></a><em> and follow </em><a href="https://noltic.com?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=update+all+subscribers"><em>Noltic</em></a><em> on </em><a href="https://www.linkedin.com/company/noltic/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.facebook.com/noltic/"><strong><em>Facebook</em></strong></a><em>, and </em><a href="https://twitter.com/realNoltic"><strong><em>Twitter</em></strong></a><em> to stay updated about our news.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f1c6e28403a6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/update-all-subscribers-salesforce-marketing-cloud-data-sync-with-sales-cloud-f1c6e28403a6">Update All Subscribers — Salesforce Marketing Cloud Data Sync with Sales Cloud</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[List Detective Report for Subscribers Data Consistency — Salesforce Marketing Cloud Guide]]></title>
            <link>https://medium.com/noltic/list-detective-report-for-subscribers-data-consistency-salesforce-marketing-cloud-guide-c7d5eb2b8a15?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/c7d5eb2b8a15</guid>
            <category><![CDATA[marketing-cloud]]></category>
            <category><![CDATA[salesforce]]></category>
            <category><![CDATA[salesforce-development]]></category>
            <dc:creator><![CDATA[Andrii Demchuk]]></dc:creator>
            <pubDate>Thu, 07 Sep 2023 14:06:01 GMT</pubDate>
            <atom:updated>2023-09-08T12:41:57.048Z</atom:updated>
            <cc:license>http://creativecommons.org/licenses/by/4.0/</cc:license>
            <content:encoded><![CDATA[<h3><strong>List Detective Report for Subscribers Data Consistency — Salesforce Marketing Cloud Guide</strong></h3><p>Salesforce Marketing Cloud is greatly dependent on the user database that the business keeps in their Sales Cloud setup. Having data inconsistencies affects communication with customers and muddles the view of an active audience.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*B6AE_ZM_evIsqU7wf3nxeg.png" /></figure><p>When updated data about Subscribers and their status is exported from Salesforce Sales Cloud to the Marketing Cloud data extension, we often want to track the number and identity of Subscribers that have been updated successfully. Having a list of the Subscribers that have encountered an issue in the process, such as having an invalid email address, significantly advances data accuracy. To achieve this, we need to follow these steps:</p><ol><li>Create Data Extension</li><li>Create Custom List Detective</li><li>Automation: Get subscribers from CRM</li><li>Automation: ExportAllSubscribers</li><li>Automation: Send List Detective report</li></ol><p>To get started, we also need to create an FTP Account (File Transfer Protocol account) for transferring files with a host computer using FTP services, which we will use in the Automation process. To do this, go to Setup &gt; Administration &gt; Data Management &gt; FTP Accounts. Then, in FTP Accounts, click on ‘Create User.</p><blockquote>Important! By default, the report does not include the fields ‘Email Address’ and ‘Subscriber Key.’ To make these fields appear, we must file a support case requesting their addition.</blockquote><h3>Create Data Extension</h3><p>Let’s create a Data Extension with the necessary fields and name it ‘All Subscribers Data’. For example, we can create a Data Extension with three fields:</p><ul><li>Subscriber Key;</li><li>Status (subscription status);</li><li>Email Address (subscriber email).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/920/1*y6vEQEoWOib23chb8CGtGw.png" /></figure><p>The Data Extension must contain information about all subscribers from Sales Cloud. You can use the Query Activity in Automation to populate this Data Extension.</p><h3><strong>Create Custom List Detective</strong></h3><p>Let’s create a List with the name ‘List Detective’:</p><ol><li>Click on ‘Subscribers’;</li><li>Choose ‘My Subscribers’;</li><li>Navigate to ‘My Lists’;</li><li>Click ‘Create’;</li><li>Select ‘Public’ to display the publication list in the subscription center;</li><li>Save your changes by clicking ‘Save’.</li></ol><p>Now, we can see our created list with fields, like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0S5kcqtV5AiSsk_2tdhF6w.png" /></figure><h3><strong>Automation: Get subscribers from CRM</strong></h3><p>Navigate to Automation Studio in Journey Builder and create a new automation called ‘List Detective Report’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/222/0*9bUJPlG1zIiM1Wvk" /></figure><p>Select the ‘Data Extract’ activity and drag it to the right on the Canvas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/307/0*9Hpvn5m6Eo24RLXu" /></figure><p>After clicking ‘Create New Data Extract Activity’, click ‘Choose’ in Data Extract.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WiisudxyH-IeDGYn" /></figure><p>In the Properties section, enter ‘Get subscribers from CRM’ in the Name field. In the File Naming Pattern field, input the desired file name, for example, ‘NotSentEmail’. Then, select ‘Data Extension Extract’ as the Extract Type. Finally, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*JbxnCrp9NirCnhz5" /></figure><p>In the Configuration section, select ‘Has Column Headers’ and enter a ‘,’ (comma) in the Column Delimiter field. For the DECustomer Key, enter the External Key Data Extension we created earlier. Then, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OpPMERYS7rlsIEKe" /></figure><p>In summary, check the input data and click ‘Finish’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AULpmSlhjoNO0Oap" /></figure><h3><strong>Automation: ExportAllSubscribers</strong></h3><p>Select the ‘File Transfer’ activity and drag it to the right on the Canvas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/587/0*-v2OdsfwwWelmW3H" /></figure><p>After clicking ‘Create New File Transfer Activity,’ click ‘Choose’ in File Transfer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9eyxVkBDIiHnGCPe" /></figure><p>In the Properties section, fill in the Name field with ‘Export All Subscribers’. Choose ‘Move a File From Safehouse’ as the File Action, then click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*XMC8k6sSdGra6B6Q" /></figure><p>In the Configuration section, enter ‘NotSentEmail’ in the File Naming Pattern field. In the Destination field, choose ‘ExactTarget Enhanced FTP’. Click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*j0j0TJ7C0LIzXtOD" /></figure><p>In summary, check the input data and click ‘Finish’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fW-30Li1MxKkDWHj" /></figure><h3><strong>Automation: Send List Detective report</strong></h3><p>Select the ‘Import File’ activity and drag it to the right on the Canvas.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/874/0*n2JHmXTwSI2P7Mbv" /></figure><p>After clicking ‘Create New Import Definition’, click ‘Choose’ in the Import File.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GNQRpXSKrKw9nBXU" /></figure><p>In the Properties section, enter ‘Send List Detective report’ in the Name field. If you want to receive emails with this data in .txt format, select ‘Send notification email to:’ and provide your email address. Finally, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*RR3JqgMh_c84IVA9" /></figure><p>In the Import File section, select ‘ExactTarget Enhanced FTP’ as the File Location. Enter ‘NotSentEmail’ in the File Naming Pattern field. On the right-hand side, in the ‘Delimiter’ section, choose ‘Comma’. Make sure to unselect ‘Respect double quotes (“) as a text delimiter’. Finally, click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AyFvHweuixP4LOJP" /></figure><p>In Destination select ‘Subscriber List’, click on the My Lists folder, and select ‘List Detective’. Click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*swyOsOvth7xku0et" /></figure><p>Select ‘Add and Update’ in Mapping and click ‘Next’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bRqM37S2oouE2rBh" /></figure><p>In the Review section, check the input data and click ‘Finish’.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*g5LFEDUHvvlCEKsz" /></figure><p>After completing the previous steps, you can schedule this automation to be executed every 24 hours, ensuring that the data is always updated with Sales Cloud.</p><p><em>Read our other </em><a href="https://medium.com/noltic"><em>Medium posts</em></a><em> and follow </em><a href="https://noltic.com?utm_source=article&amp;utm_medium=medium&amp;utm_campaign=list+detective+report"><em>Noltic</em></a><em> on </em><a href="https://www.linkedin.com/company/noltic/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.facebook.com/noltic/"><strong><em>Facebook</em></strong></a><em>, and </em><a href="https://twitter.com/realNoltic"><strong><em>Twitter</em></strong></a><em> to stay updated about our news.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c7d5eb2b8a15" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/list-detective-report-for-subscribers-data-consistency-salesforce-marketing-cloud-guide-c7d5eb2b8a15">List Detective Report for Subscribers Data Consistency — Salesforce Marketing Cloud Guide</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Seamless Salesforce Data Generation: A Journey Towards Realistic Field Values and Efficient…]]></title>
            <link>https://medium.com/noltic/seamless-salesforce-data-generation-a-journey-towards-realistic-field-values-and-efficient-2a0710d0f69f?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/2a0710d0f69f</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[sfdx]]></category>
            <category><![CDATA[data-generation]]></category>
            <category><![CDATA[salesforce]]></category>
            <category><![CDATA[data]]></category>
            <dc:creator><![CDATA[Oleksandr Adamovsky]]></dc:creator>
            <pubDate>Mon, 24 Jul 2023 12:31:39 GMT</pubDate>
            <atom:updated>2023-07-24T13:19:51.180Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*A0WPSyaHovk3DFYUzFV3bA.jpeg" /></figure><h3><strong>Seamless Salesforce Data Generation: A Journey Towards Realistic Field Values and Efficient Relationships</strong></h3><p>What would you do if you were asked to generate thousands of opportunities, with different opportunity teams, connected to different contacts &amp; accounts, at different stages of pipeline, and to top that — with products and prices? What if the client asked you to avoid using “Lorem ipsum” or “Test Test” contacts and instead use real names and addresses from a specific list of companies? Maybe you were also asked to include numerous relationships, possibly more than just a few?</p><p>Given the challenging nature of this task and its specific requirements, I would like to share my experience in data generation for Salesforce to share my knowledge with you and make your journey much smoother. 🙂</p><p>By acknowledging the data model and utilizing SFDX scripts, bash scripts, and various services, together we’ll discover how to efficiently generate and deploy data while minimizing manual interventions. So, without further ado, let’s dive into the details.</p><p>You probably already know that you can use <a href="https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_force_data.htm"><strong>sfdx data</strong> <strong>commands</strong></a> to import data to Salesforce. It’s a powerful tool that is used exactly for data import. It’s easy to insert related data using the reference. But there are few limitations:</p><ul><li>You can only insert up to 200 records per file;</li><li>You can’t include references to records that are already in the org. For example, you won’t be able to link an existing Standard Pricebook Id if you insert Pricebook Entry records.</li></ul><p>I’ve been doing import &amp; export operations for sample data using <a href="https://workbench.developerforce.com/login.php?startUrl=%2Finsert.php">Workbench</a> and <a href="https://dataloader.io">Dataloader.io</a>. Both are capable of data manipulation, but Dataloader.io has restrictions toward the maximum number of data to be processed, which is 10000 records/month for a free license. So I chose Workbench, but you may use other, better tools.</p><p>To generate records, I have utilized various services that offer flexibility in configuring different values. Among them is the <a href="https://www.convertcsv.com/generate-test-data.htm">Convertcsv</a> web service, which initially appeared helpful. However, as I considered the process of linking related records, I found that Python would be a highly convenient option for data processing. The idea of performing fake data generation within the same environment seemed like a perfect solution to me.</p><p>My expertise in this programming language is somewhat limited, so I was a bit cautious about getting sucked into all the libraries and figuring out all the language-specific things, but after a few attempts I realized that my goals can be easily reached with help of ChatGPT. I found a library called <a href="https://faker.readthedocs.io/en/master/"><strong>Faker</strong></a><strong>, </strong>which helped me create fake data in the quickest and simplest way. It made the entire process much more convenient because I could try various options and generally felt more confident about it.</p><p>To give you a little bit of insight, the following code can generate company names. We can use them to enter into the Account Name field.</p><pre>from faker import Faker<br>accNames = [Faker().company() for _ in range(5)]<br># Result: [&#39;Davis-Davis&#39;, &#39;Johnson, Haas and Wagner&#39;, &#39;Thomas Group&#39;, &#39;Wilson-Lewis&#39;, &#39;Wade, Fuller and Anderson&#39;]</pre><p>Faker allows us to generate different kinds of dummy data, like:</p><ul><li>company()</li><li>url()</li><li>phone_number()</li><li>word()</li><li>city(), street_address(), country()</li><li>email()</li><li>first_name(), last_name()</li><li>date_of_birth()</li></ul><p>Based on the example &amp; methods above, you can see that I’ve played around and came up with a script that can generate a number of accounts, with some of the fields filled. You may need to include additional or other fields, but these were enough in my case.</p><pre>import csv<br>from faker import Faker<br><br>fake = Faker()<br><br><br># Number of Salesforce Accounts to generate<br>num_accounts = 2000<br># CSV file where to output data<br>output_file = &quot;salesforce_accounts.csv&quot;<br><br># Define field names for the CSV file<br>field_names = [&quot;Name&quot;, &quot;Phone&quot;, &quot;Email&quot;, &quot;BillingStreet&quot;, &quot;BillingCity&quot;, &quot;BillingState&quot;, &quot;BillingPostalCode&quot;]<br><br># Generate Salesforce Accounts<br>accounts = []<br>for _ in range(num_accounts):<br>   account = {<br>       &quot;Name&quot;: fake.company(),<br>       &quot;Phone&quot;: fake.phone_number(),<br>       &quot;Email&quot;: fake.email(),<br>       &quot;BillingStreet&quot;: fake.street_address(),<br>       &quot;BillingCity&quot;: fake.city(),<br>       &quot;BillingState&quot;: fake.state(),<br>       &quot;BillingPostalCode&quot;: fake.postcode(),<br>   }<br>   accounts.append(account)<br><br># Save Salesforce Accounts to CSV file<br>with open(output_file, &quot;w&quot;, newline=&quot;&quot;) as file:<br>   writer = csv.DictWriter(file, fieldnames=field_names)<br>   writer.writeheader()<br>   writer.writerows(accounts)<br><br>print(f&quot;{num_accounts} Salesforce Accounts generated and saved to {output_file}.&quot;)<br><br># Result:<br># Name,Phone,Email,BillingStreet,BillingCity,BillingState,BillingPostalCode<br># Stevenson LLC,(106)049-6070,fernandezshannon@example.org,73037 Owen Shoal Suite 720,Kingburgh,Nebraska,06298<br># Sullivan Inc,3417264849,walshseth@example.net,789 Williams Dam,Torreshaven,Wisconsin,57778<br>#...</pre><p>When it comes to records that <strong>do not have</strong> lookup relationships, managing them is quite easy, but if the records do have such relationships, you can create an extra Python service to handle this case.</p><p>We created the file <strong>NotLinkedContacts.csv</strong> using the same approach employed for Account generation, incorporating all necessary fields with representative sample data. AccountId is the only field that was left empty, so we can add Ids later.</p><p>After generating and importing the Account records, they now possess unique Ids within the system. To proceed, I had to export these records through Workbench, including their Id values, so that I could utilize them later in the creation of a file containing Contact records with the AccountId field filled in. I saved this file as <strong>AccountsWithIds.csv</strong>.</p><p>I have created the following script for linking the Contact records with Accounts:</p><pre>import sys<br>import csv<br><br>input_file = sys.argv[1]<br>output_file = sys.argv[2]<br>object_type = sys.argv[3]<br><br># Read the Accounts.csv file and get the Id values<br>account_ids = []<br>with open(&#39;AccountsWithIds.csv&#39;, &#39;r&#39;) as accounts_file:<br>   reader = csv.DictReader(accounts_file)<br>   for row in reader:<br>       account_ids.append(row[&#39;Id&#39;])<br><br># Update the input file with the Account Id values<br>with open(input_file, &#39;r&#39;) as input_csv:<br>   data = list(csv.DictReader(input_csv))<br>   fieldnames = [&#39;FirstName&#39;, &#39;LastName&#39;, &#39;Email&#39;, &#39;Phone&#39;, &#39;Title&#39;, &#39;Fax&#39;, &#39;Birthdate&#39;, &#39;Department&#39;,&#39;MailingCountry&#39;, &#39;MailingStreet&#39;, &#39;MailingCity&#39;, &#39;MailingPostalCode&#39;, &#39;LeadSource&#39;, &#39;AccountId&#39;]<br><br><br>   for i, row in enumerate(data):<br>       # Cycle through the account_ids list<br>       row[&#39;AccountId&#39;] = account_ids[i % len(account_ids)] <br><br># Write the updated data back to the output file<br>with open(output_file, &#39;w&#39;, newline=&#39;&#39;) as output_csv:<br>   writer = csv.DictWriter(output_csv, fieldnames=fieldnames)<br>   writer.writeheader()<br>   writer.writerows(data)<br><br>print(&quot;CSV file updated successfully.&quot;)</pre><p>The linking process can be outlined as follows:</p><ol><li>We are retrieving Ids of the accounts into array;</li><li>We are assigning the AccountId in a cyclic manner to Contacts that have been previously generated. This means that if there are more contacts than accounts, we cycle through them repeatedly, starting from the first account and continuing until all contacts have been assigned an AccountId;</li><li>We save this into a <strong>LinkedContacts.csv</strong> file.</li></ol><p>The script uses arguments provided to it as input. This method allowed me to develop a generic approach for establishing relationships between records of different types. Below is an outline of how the script execution would proceed.</p><pre>python3 &lt;service_name&gt;.py &lt;input_name_not_linked&gt;.csv &lt;output_name_linked&gt;.csv</pre><p>Example:</p><pre>python3 linkService.py NotLinkedContacts.csv LinkedContacts.csv</pre><p>And now, when the Contacts are linked, you can use a tool of choice to deploy them to the org.</p><p><strong>How Bash scripts might help?</strong></p><p>As part of my project, deploying Products to the organization was essential for their use in Opportunity Line Items. For those familiar with Products, Pricebooks, and Opportunities, you may know that in order to utilize Products within an Opportunity, they must have at least one Pricebook Entry in the Standard Pricebook. This Standard Pricebook is automatically generated in the organization.</p><p>Currently, I haven’t found a standard or more efficient method to insert Products with prices into the Pricebook Entry of the Standard Pricebook. For my requirement of inserting only 20 products (along with other objects where the quantity was &lt; 200), I followed the initial approach outlined in the article. It’s worth mentioning that the Python script would be quite similar in this scenario.</p><pre>sfdx force:data:tree:import</pre><p>The command above can deploy some sObject records directly by specifying the corresponding .json file. Alternatively, we can use a special plan containing a list of sObjects and their respective JSONs.</p><p>Plan example:</p><pre>[<br> {<br>   &quot;sobject&quot;: &quot;sobject_api_name&quot;,<br>   &quot;saveRefs&quot;: true,<br>   &quot;resolveRefs&quot;: true,<br>   &quot;files&quot;: [&quot;file_with_records.json&quot;]<br> },<br>…<br>]</pre><p>The contents of the <strong>file_with_records.json</strong> will look like this:</p><pre>{<br> &quot;records&quot;: [<br>   {<br>     &quot;attributes&quot;: {<br>       &quot;type&quot;: &quot;sobject&quot;,<br>       &quot;referenceId&quot;: &quot;someReferenceName1&quot; // e.g AccountRef, ContactRef…<br>     },<br>     field1_api: value1,<br>     field2_api: value2,<br>     …<br>   },<br>   {<br>     &quot;attributes&quot;: {<br>       &quot;type&quot;: &quot;sobject&quot;,<br>       &quot;referenceId&quot;: &quot;someReferenceName2&quot;<br>     },<br>     field1_api: value1,<br>     field2_api: value2,<br>     …<br>   },<br>…<br>  ]<br>}<br></pre><p>And now, how to get the Id of the Standard Pricebook? A little bit of magic with the bash scripts and it’s all done!</p><p>So, I am going to add text <strong>placeholders</strong> in JSON files with records to <strong>replace</strong> them with bash:</p><p><strong>PricebookEntries.template.json</strong></p><pre>{<br> &quot;records&quot;: [<br>   {<br>     &quot;attributes&quot;: {<br>       &quot;type&quot;: &quot;PricebookEntry&quot;,<br>       &quot;referenceId&quot;: &quot;PBERef1&quot;<br>     },<br>     &quot;UnitPrice&quot;: 3000,<br>     &quot;Product2Id&quot;: &quot;@ProductReference1&quot;,<br>     &quot;Pricebook2Id&quot;: &quot;@StandardPricebookPlaceHolder&quot;,<br>     &quot;IsActive&quot;: true<br>   },<br>…<br>  ]<br>}<br></pre><p>This is a <strong>.template</strong> file that has a placeholder for StandardPricebook (@StandardPricebookPlaceholder) which will be substituted with the actual value from the org using bash scripts.</p><p>Salesforce CLI provides the possibility to query data from the org using the terminal by <strong>sfdx data:query</strong> <strong>-q &lt;soql_query&gt;</strong>. By using such functionality, I was able to get Standard Pricebook Id.</p><pre>STANDARD_PRICEBOOK_ID=&quot;$(sfdx data:query -q &quot;SELECT Id FROM Pricebook2 WHERE IsStandard=true LIMIT 1&quot; -o $TargetOrg -r csv | grep 01)&quot;</pre><p>After obtaining the required Id, we utilized the <strong>sed</strong> command to replace the Id in the relevant locations. This command facilitates the replacement of a specific string with the desired value, and we saved the updated results as a separate <strong>PricebookEntries.json</strong> file.</p><pre>sed &quot;s/@StandardPricebookPlaceHolder/${STANDARD_PRICEBOOK_ID}/g&quot; ./data/PricebookEntries.template.json &gt; ./data/PricebookEntries.json</pre><p>The state of PricebookEntries.json:</p><pre>{<br> &quot;records&quot;: [<br>   {<br>     &quot;attributes&quot;: {<br>       &quot;type&quot;: &quot;PricebookEntry&quot;,<br>       &quot;referenceId&quot;: &quot;PBERef1&quot;<br>     },<br>     &quot;UnitPrice&quot;: 3000,<br>     &quot;Product2Id&quot;: &quot;@ProductReference1&quot;,<br>     &quot;Pricebook2Id&quot;: &quot;01s7R000006H1alQAC&quot;,<br>     &quot;IsActive&quot;: true<br>   },<br>…<br>  ]<br>}</pre><p>You can notice that the value in Pricebook2Id was replaced with the actual Id.</p><p>Finally, we can simply execute <strong>sfdx data:tree:import </strong>to deploy the needed records.</p><pre>sfdx force:data:tree:import -p PlanForProducts.json -u $TargetOrg</pre><p>Where PlanForProducts.json looks like:</p><pre>[<br> {<br>   &quot;sobject&quot;: &quot;Product2&quot;,<br>   &quot;saveRefs&quot;: true,<br>   &quot;resolveRefs&quot;: true,<br>   &quot;files&quot;: [&quot;Product2.json&quot;]<br> },<br> {<br>   &quot;sobject&quot;: &quot;PricebookEntry&quot;,<br>   &quot;saveRefs&quot;: true,<br>   &quot;resolveRefs&quot;: true,<br>   &quot;files&quot;: [&quot;PricebookEntries.json&quot;]<br> }<br>]</pre><p>The order of objects is very crucial in deployment as <strong>data:tree:import</strong> has the ability to link objects within one transaction.</p><p>When inserting a record of Product2, its ID is stored, allowing for future reference and linkage with other records. Here is an example of the records that are going to be inserted:</p><pre>{<br>  &quot;records&quot;: [<br>    {<br>      &quot;attributes&quot;: {<br>        &quot;type&quot;: &quot;Product2&quot;,<br>        &quot;referenceId&quot;: &quot;PRODRef1&quot;<br>      },<br>      &quot;Name&quot;: &quot;StellarGlo&quot;<br>    },<br>    ...<br>  ]<br>}</pre><p>By utilizing <strong>ProductReference1</strong> in lookup fields, records will be immediately linked, just as it was done for <strong>PricebookEntries.json</strong> before.</p><pre>…<br>   {<br>     &quot;UnitPrice&quot;: 3000,<br>     &quot;Product2Id&quot;: &quot;@ProductReference1&quot;,<br>     &quot;Pricebook2Id&quot;: &quot;01s7R000006H1alQAC&quot;,<br>     &quot;IsActive&quot;: true<br>   },<br>…</pre><p>I applied a similar approach to insert Users, connecting them to existing Roles and Profiles. In the .json file that contains Users, I deliberately left placeholders, which were later replaced with the correct values obtained through the <strong>sfdx data:query</strong> command, assisted by <strong>sed</strong>.</p><p><strong>Conclusion</strong></p><p>In summary, the journey of generating and managing Salesforce sample data has provided immense value. By creating 5000 Leads, 2000 Accounts, 2000 Contacts, and 4000 Opportunities, we formed a comprehensive and interconnected dataset. This valuable information allows for a better understanding of customers, prospects, and their interactions. Moreover, by linking Opportunity Line Items and Opportunity Team Members, the collaboration improved, resulting in increased sales productivity. These efforts underscore the importance of effective data management in making informed decisions, targeted marketing, and efficient sales operations.</p><p>Using the approaches mentioned earlier saved me a lot of time and made it much easier to create and manage fake data, including modifying records. These services simplified the process and were especially useful when dealing with small chunks of data that needed to be linked together. <strong>sfdx force:data:tree:import</strong> was particularly helpful in these scenarios.</p><p><strong>HINT</strong>: For the LeadSource field or picklist fields you can use the following function:</p><pre>random.choice(stringArr[&#39;opt1&#39;,&#39;opt2&#39;...])</pre><p><em>Read our other </em><a href="https://medium.com/noltic"><em>Medium posts</em></a><em> and follow Noltic on </em><a href="https://www.linkedin.com/company/noltic/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.facebook.com/noltic/"><strong><em>Facebook</em></strong></a><em>, and </em><a href="https://twitter.com/realNoltic"><strong><em>Twitter</em></strong></a><em> to stay updated about our news.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2a0710d0f69f" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/seamless-salesforce-data-generation-a-journey-towards-realistic-field-values-and-efficient-2a0710d0f69f">Seamless Salesforce Data Generation: A Journey Towards Realistic Field Values and Efficient…</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Salesforce ’20 Release: LMS, Dynamic Forms, User Permissions and more]]></title>
            <link>https://medium.com/noltic/salesforce-20-release-lms-dynamic-forms-user-permissions-and-more-58b4cede495b?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/58b4cede495b</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[salesforce-productivity]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[salesforce]]></category>
            <category><![CDATA[crm]]></category>
            <dc:creator><![CDATA[Serhiy Maksymchuk]]></dc:creator>
            <pubDate>Thu, 10 Sep 2020 07:02:50 GMT</pubDate>
            <atom:updated>2020-09-10T09:00:22.065Z</atom:updated>
            <content:encoded><![CDATA[<p>Salesforce is generous with releasing new features, pleasing the community with three seasonal releases each year: Spring, Summer, and Winter.</p><p>The Salesforce Summer 2020 release sprouted a lot of reviews and questions. But we wanted to give you more practical feedback about the newly introduced features, the experience we had on projects before they were introduced, what they could be useful for, and any limitations we see about these features. After all, Noltic is a 100% Salesforce solution vendor, so we know a thing or two about the platform.</p><p>Ready? Let’s go!</p><h3>Introducing Dynamic Forms</h3><p>This is probably the best feature Salesforce introduced in the Summer ’20 release, and that’s why it’s number one on our list. This was actually requested a few times by our customers, so yay.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Qp-IKt6N1JW8YDJb.png" /></figure><p>Previously, to accomplish this, we had to build custom components and use fieldsets to allow customers to dynamically select fields that would appear on different parts of the page, as opposed to a monolithic block of fields in one place.</p><p>Another cool thing is that you can now leverage visibility rules to show and/or hide sections and fields. With this step, Salesforce has really outdone itself in terms of bringing flexible no-code solutions to its clients.</p><p>Unfortunately, we can’t use custom dynamic forms in development, so the feature is useful for administrators only.</p><p><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_forcecom_lab_dynamic_forms.htm">Click here</a> to learn more about this update.</p><h3>Lightning Message Service Integration</h3><p>Lightning Message Service (LMS) is a library that improves communication between UI components. The main problem LMS solves is various approaches to publishing and receiving messages across the Visualforce, Aura, and LWC components.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*kqJx0ip88KDTN0do.png" /></figure><p>The components of the library include:</p><ul><li><strong>Message Channel</strong>. The main component that enables messaging via LMS. To address it, code <em>@salesforce/messageChannel</em> in LWC, <em>$MessageChannel</em> global variable in Visualforce components, and <em>lightning:messageChannel</em> in Aura components.</li><li><strong>Scope</strong>. Defines the context for publishing, i.e., which subscriber components will receive messages. There are two scopes: active (default) and application. The active scope includes subscribers only from the active area of the application. The application or global scope ensures that all subscribers get the message, even if that application area is inactive.</li><li><strong>Publish</strong>. A method to send messages through a message channel.</li><li><strong>Subscribe</strong>. A method to receive messages from a message channel.</li></ul><p>LMS makes communication across different components flexible and straightforward. Plus, it’s easier to develop and maintain connected components.</p><p><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_lc_message_channel.htm">Click here</a> to learn more about this update.</p><h3>CSS Style Sharing within Lightning Web Components</h3><p>With this release, you can also share CSS styles within Lightning Web Components. Now, it’s easier than ever to share code as well as styles and extend the styles of basic components in just a few clicks. This feature will come especially in handy when working with sets of extendable components.</p><p>You can also achieve a similar result using SCSS in LWC. It features a slightly different syntax, though, since you need to reference the file instead of the component itself.</p><p><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_lwc_css_share.htm">Click here</a> to learn more about this update.</p><h3>Status Inquiry for Asynchronous Platform Event Publish Operations (Pilot Feature)</h3><p>Now you can track the status of the logic executed under platform events using the publish status events. This feature is especially useful when you need to get the results after publishing events, regardless of their occurrence.</p><p>Imagine you need to run some synchronization with platform events and send some payload inside. Sometimes, the sync may fail due to various reasons, like the lack of the necessary data, bad data updating conditions, etc. Currently, we can only identify whether events were published or not, but receive no information about the logic execution inside platform event triggers, so publishers can’t determine if it was successful or not.</p><p>To make sending the execution status possible, you can create a separate platform event and error handling logic. This new feature will make everything available out of the box, eliminating the need for custom status notification mechanisms. This will also reduce the amount of work necessary for building these notifying mechanisms.</p><p>Unfortunately, it’s a pilot feature, so you can’t request it now. So it’s hard to tell how it will respond to different error types, retries, etc.</p><p><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_platform_events_publish_status.htm">Click here</a> to learn more about this update.</p><h3>Removing Lightning Components from Managed Packages</h3><p>As the Salesforce platform improves, some components get removed, deprecated, or replaced with newer and better ones.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Vujulazp4YaZj721.png" /></figure><p>Up until now, there was no way to delete LWC &amp; Lightning components from a managed package. With this new feature, Salesforce ISV partners can improve their products by removing the components that are no longer necessary.</p><p><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_lc_delete_from_package.htm">Click here</a> to learn more about this update.</p><h3>SFDX (Second-Generation Packages)</h3><p>It looks like Salesforce is betting on second-generation packages, with quite a few features released to help with their development as well as converting first-generation packages to second-generation. These are the features we’re talking about:</p><ul><li><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_sfdx_packaging_get_ready_code_coverage.htm">Package code coverage enforcement</a></li><li><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_sfdx_packaging_preview_package_migration.htm">An early look at converting first-generation managed packages</a> (Developer Preview)</li><li><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_sfdx_packaging_org_dependent_packages.htm">Org-Dependent unlocked packages</a></li><li><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_sfdx_packaging_push_upgrade_2GP.htm">Upgrades to unlocked and second-generation managed packages</a> (Beta)</li></ul><p><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_lc_delete_from_package.htm">Click here</a> to learn more about this update.</p><h3>Aura Components in the ui Namespace to Be Deprecated</h3><p>Starting from May 1, 2021, Salesforce will stop supporting Aura components in the ui namespace. So, if you’re still using them, consider looking at the component in the lightning namespace or writing custom ones.</p><p><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_aura_ui_deprecate.htm">Click here</a> to learn more about this update.</p><h3>User Permissions for Lightning Web Components</h3><p>Salesforce has a flexible permission system. There are two types of permissions: system and custom permissions, which are stored in Profile and Permission Sets. Checking those permissions has become truly effortless.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*IGDjp1c5IcviSJCY.png" /></figure><p>Look at this code sample. It’s as easy as importing a static reference.</p><pre>import hasPermission from &#39;@salesforce/userPermission/PermissionName&#39;;</pre><p>Now, imagine you want to know if a user has permission to see an expense report. The following code snippets are succinct and sufficient.</p><pre>//ExpenseReport.js</pre><pre>import { LightningElement } from &#39;lwc&#39;;</pre><pre>import hasViewReport from &#39;@salesforce/customPermission/acme__ViewReport&#39;;</pre><pre>export default class App extends LightingElement {</pre><pre>    get isReportVisible() {</pre><pre>        return hasViewReport;</pre><pre>    }</pre><pre>}</pre><pre>//ExpenseReport.html</pre><pre>&lt;template if:true={isReportVisible}&gt;</pre><p><a href="https://releasenotes.docs.salesforce.com/en-us/summer20/release-notes/rn_lwc_access_permissions.htm">Click here</a> to learn more about this update.</p><p>It might be hard to keep track of all the innovations SFDC is rolling out, so keep that ear to the ground! We hope the comments Noltic’s experts gave on the eight updates of the summer ’20 release were as useful for you as they were exciting for us. And if you liked them, check out other articles in Noltic’s blog. Stay tuned!</p><p><em>Originally published at </em><a href="https://noltic.com/blog/sfdc-release-comments/"><em>https://noltic.com/</em></a> <em>on September 8, 2020.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/806/1*Nn5Xgocn-_CxpI6inncgXA.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=58b4cede495b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/salesforce-20-release-lms-dynamic-forms-user-permissions-and-more-58b4cede495b">Salesforce ’20 Release: LMS, Dynamic Forms, User Permissions and more</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Noltic has created the library for parsing and validating international phone numbers in Salesforce]]></title>
            <link>https://medium.com/noltic/noltic-has-created-the-library-for-parsing-and-validating-international-phone-numbers-in-salesforce-5163a984681b?source=rss----ff471d048f3a---4</link>
            <guid isPermaLink="false">https://medium.com/p/5163a984681b</guid>
            <category><![CDATA[appexchange]]></category>
            <category><![CDATA[salesforce]]></category>
            <category><![CDATA[libphonenumber]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[product]]></category>
            <dc:creator><![CDATA[Igor Petrovych]]></dc:creator>
            <pubDate>Fri, 31 Jul 2020 12:44:44 GMT</pubDate>
            <atom:updated>2023-06-19T08:09:04.792Z</atom:updated>
            <content:encoded><![CDATA[<h3>Noltic has created a native app for parsing and validating international phone numbers in Salesforce</h3><p><em>Originally published on July 31, 2020. Updated on June 19, 2023</em></p><p>For a business, phone numbers are usually the primary contact information of their customers and the key to long-running relations. The ability to collect valid phone numbers and operate them in accordance with their type, region or time zone can hugely decrease the time for business owners to close a deal.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zhozEhHzjghx3rep.jpeg" /><figcaption>CheckMyNumber by Noltic: parsing, formatting, and validating phone numbers for all countries/regions of the world. Native Salesforce app. Available on AppExchange.</figcaption></figure><p>For businesses running on Salesforce, there haven’t been any native solutions to effectively validate phone numbers, check them against proper length, format and country code.</p><p>One of our clients was looking for a solution compatible with their technology stack, and since there was no alternative, we put together our own ready-to-use product — CheckMyNumber. We originally released it on AppExchange under the name Libphonenumber, proudly becoming the trailblazers in the field of phone number formatting and validation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QAMs7ZrjpoBuZepxQWEpAQ.jpeg" /></figure><h3>Features &amp; functionality</h3><ul><li>Parsing, formatting, and validating phone numbers for all countries/regions of the world.</li><li>Recognition of the phone number type with the ability to distinguish Fixed-line, Mobile, Toll-free, Premium Rate, Shared Cost, VoIP, Personal Numbers, UAN, Pager, and Voicemail (whenever feasible)</li><li>Providing a confidence level on whether two numbers could be the same.</li><li>Providing valid sample numbers for all countries/regions with the option to specify which type of sample phone number is needed.</li><li>Quick estimation/guess of a phone number validity by its length only, much faster than a full validation.</li><li>Full validation of a phone number for a region using length and prefix information.</li><li>Phone numbers formatting on-the-fly when users enter each digit.</li><li>Finding phone numbers within text.</li><li>Providing the original carrier, timezone and location data related to a phone number.</li></ul><blockquote>“With the ability to format, validate and parse phone numbers directly in their Salesforce instances, our customers are instantly receiving reliable data without much effort to stay in direct contact with their client base. And that’s exactly what we wanted to deliver through our solution”, says Vladyslav Petrovych, CTO at Noltic</blockquote><p>We regularly update our app with the latest phone metadata, bug fixes, and other improvements per client requests. Among the latest updates are some automated and declarative features. It made our app even more accessible as a no-code solution and decreased the time needed for adoption. This way we satisfy even more Salesforce users who are looking for a quick and dependable solution for their needs.</p><p><a href="https://appexchange.salesforce.com/appxListingDetail?listingId=a0N3A00000G12oJUAR">Start using CheckMyNumber with a free 14-day trial</a><strong>.</strong></p><p><em>Read our other </em><a href="https://medium.com/noltic"><em>Medium posts</em></a><em> and follow Noltic on </em><a href="https://www.linkedin.com/company/noltic/"><strong><em>LinkedIn</em></strong></a><em>, </em><a href="https://www.facebook.com/noltic/"><strong><em>Facebook</em></strong></a><em>, and </em><a href="https://twitter.com/realNoltic"><strong><em>Twitter</em></strong></a><em> to stay updated about our news.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5163a984681b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/noltic/noltic-has-created-the-library-for-parsing-and-validating-international-phone-numbers-in-salesforce-5163a984681b">Noltic has created the library for parsing and validating international phone numbers in Salesforce</a> was originally published in <a href="https://medium.com/noltic">Noltic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>