As an alternative to the Sendoso Chrome extension, you can add a Lightning Web Component or a Visualforce page (SFDC Lightning) to complete one-to-one sends. LWC or Visualforce page can be placed on any object; however, Sendoso recommends putting it on the lead and contact objects to pull in recipient information.
**Note - You will need Salesforce admin permissions to complete this setup
Salesforce Visualforce page Setup
To get started, go to ‘Setup’ and find Visualforce Pages.
Create a new Visualforce page.
Name it ‘Sendoso’ or ‘Gifting’, make sure to include lead or contact in the name, depending on the object you want to add this to.
Check the box to make available for lightning experiences, experience builder sites, and the mobile app.
Copy the code block for either the lead or contact:
Code Block for Contact Object:
<apex:page standardController="Contact" showHeader="false" sidebar="false">
<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap');
html, body { height: 100%; margin: 0; padding: 0; overflow: hidden; }
body { font-family: 'Roboto', sans-serif; background: #ffffff; }
#tabBar { display: flex; gap: 1rem; padding: 0 16px; border-bottom: 1px solid #e5e7eb; background: #ffffff; }
.customTab { font-family: 'Roboto', sans-serif; font-size: 14px; font-weight: 500; color: #323C50; padding: 10px 4px; margin-bottom: -1px; cursor: pointer; border: none; background: none; outline: none; -webkit-font-smoothing: antialiased; text-decoration: none; }
.customTab.active { text-decoration: underline; text-decoration-color: #F37021; text-decoration-thickness: 2px; text-underline-offset: 8px; }
.customTab:hover:not(.active) { text-decoration: underline; text-decoration-color: #F37021; text-decoration-thickness: 2px; text-underline-offset: 8px; }
.tabContent { display: none; }
.tabContent.active { display: block; }
iframe { display: block; width: 100%; height: calc(100vh - 42px); border: none; }
.smartsend-container { overflow: hidden; height: calc(100vh - 42px); }
#smartSendIframe { transform: scale(0.82); transform-origin: top left; width: calc(100% / 0.82); height: calc((100vh - 42px + 80px) / 0.82); margin-top: -52px; }
.marketplace-container { overflow: hidden; height: calc(100vh - 42px); }
#marketplaceIframe { transform: scale(0.82); transform-origin: top left; width: calc(100% / 0.82); height: calc((100vh - 42px + 80px) / 0.82); margin-top: -52px; }
.dashboard-container { overflow: hidden; height: calc(100vh - 42px); }
#dashboardIframe { transform: scale(0.75); transform-origin: top left; width: calc(100% / 0.75); height: calc((100vh - 42px + 70px) / 0.75); border: none; margin-top: -52px; }
</style>
<script>
function showTab(tabName, el) {
document.querySelectorAll('.tabContent').forEach(function(tab) { tab.classList.remove('active'); });
document.querySelectorAll('.customTab').forEach(function(tab) { tab.classList.remove('active'); });
document.getElementById('tab-' + tabName).classList.add('active');
el.classList.add('active');
}
window.addEventListener('load', function() {
var email = '{!JSENCODE(Contact.Email)}';
var firstName = '{!JSENCODE(Contact.FirstName)}';
var lastName = '{!JSENCODE(Contact.LastName)}';
var fullName = '{!JSENCODE(Contact.Name)}';
var street = '{!JSENCODE(Contact.MailingStreet)}';
var city = '{!JSENCODE(Contact.MailingCity)}';
var state = '{!JSENCODE(Contact.MailingState)}';
var zip = '{!JSENCODE(Contact.MailingPostalCode)}';
var country = '{!JSENCODE(Contact.MailingCountry)}';
if (!firstName && fullName) {
var parts = fullName.trim().split(' ');
firstName = parts[0] || '';
lastName = parts.slice(1).join(' ') || '';
}
var d = btoa(JSON.stringify({ e: email }));
var ss = btoa(JSON.stringify({ e: email, fn: firstName, ln: lastName }));
document.getElementById('smartSendIframe').src =
'https://app.sendoso.com/m/send/smartsend?d=' + encodeURIComponent(d);
document.getElementById('marketplaceIframe').src =
'https://app.sendoso.com/m/manage/marketplace/readonly' +
'?recipientEmail=' + encodeURIComponent(email) +
'&recipientFirstName=' + encodeURIComponent(firstName) +
'&recipientLastName=' + encodeURIComponent(lastName) +
'&recipientAddress=' + encodeURIComponent(street) +
'&recipientCity=' + encodeURIComponent(city) +
'&recipientState=' + encodeURIComponent(state) +
'&recipientZip=' + encodeURIComponent(zip) +
'&recipientCountry=' + encodeURIComponent(country) +
'&ss=' + encodeURIComponent(ss);
});
</script>
<div id="tabBar">
<button class="customTab active" onclick="showTab('sends', this)">Send</button>
<button class="customTab" onclick="showTab('smartsend', this)">SmartSend</button>
<button class="customTab" onclick="showTab('marketplace', this)">Marketplace</button>
<button class="customTab" onclick="showTab('dashboard', this)">Dashboard</button>
</div>
<div id="tab-sends" class="tabContent active">
<iframe src="https://app.sendoso.com/v2/plugin/sends?channel=salesforce&name={!URLENCODE(Contact.Name)}&email={!URLENCODE(Contact.Email)}&company_name={!URLENCODE(Contact.Account.Name)}&address={!URLENCODE(Contact.MailingStreet)}&city={!URLENCODE(Contact.MailingCity)}&state={!URLENCODE(Contact.MailingState)}&zip={!URLENCODE(Contact.MailingPostalCode)}&country={!URLENCODE(Contact.MailingCountry)}" scrolling="auto"></iframe>
</div>
<div id="tab-smartsend" class="tabContent">
<div class="smartsend-container">
<iframe id="smartSendIframe" src="" scrolling="auto"></iframe>
</div>
</div>
<div id="tab-marketplace" class="tabContent">
<div class="marketplace-container">
<iframe id="marketplaceIframe" src="" scrolling="auto"></iframe>
</div>
</div>
<div id="tab-dashboard" class="tabContent">
<div class="dashboard-container">
<iframe id="dashboardIframe" src="https://app.sendoso.com/m/dashboard" scrolling="auto"></iframe>
</div>
</div>
</apex:page>Code Block for Lead Object:
<apex:page standardController="Lead" showHeader="false" sidebar="false">
<style>
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&display=swap');
html, body { height: 100%; margin: 0; padding: 0; overflow: hidden; }
body { font-family: 'Roboto', sans-serif; background: #ffffff; }
#tabBar { display: flex; gap: 1rem; padding: 0 16px; border-bottom: 1px solid #e5e7eb; background: #ffffff; }
.customTab { font-family: 'Roboto', sans-serif; font-size: 14px; font-weight: 500; color: #323C50; padding: 10px 4px; margin-bottom: -1px; cursor: pointer; border: none; background: none; outline: none; -webkit-font-smoothing: antialiased; text-decoration: none; }
.customTab.active { text-decoration: underline; text-decoration-color: #F37021; text-decoration-thickness: 2px; text-underline-offset: 8px; }
.customTab:hover:not(.active) { text-decoration: underline; text-decoration-color: #F37021; text-decoration-thickness: 2px; text-underline-offset: 8px; }
.tabContent { display: none; }
.tabContent.active { display: block; }
iframe { display: block; width: 100%; height: calc(100vh - 42px); border: none; }
.smartsend-container { overflow: hidden; height: calc(100vh - 42px); }
#smartSendIframe { transform: scale(0.82); transform-origin: top left; width: calc(100% / 0.82); height: calc((100vh - 42px + 80px) / 0.82); margin-top: -52px; }
.marketplace-container { overflow: hidden; height: calc(100vh - 42px); }
#marketplaceIframe { transform: scale(0.82); transform-origin: top left; width: calc(100% / 0.82); height: calc((100vh - 42px + 80px) / 0.82); margin-top: -52px; }
.dashboard-container { overflow: hidden; height: calc(100vh - 42px); }
#dashboardIframe { transform: scale(0.75); transform-origin: top left; width: calc(100% / 0.75); height: calc((100vh - 42px + 70px) / 0.75); border: none; margin-top: -52px; }
</style>
<script>
function showTab(tabName, el) {
document.querySelectorAll('.tabContent').forEach(function(tab) { tab.classList.remove('active'); });
document.querySelectorAll('.customTab').forEach(function(tab) { tab.classList.remove('active'); });
document.getElementById('tab-' + tabName).classList.add('active');
el.classList.add('active');
}
window.addEventListener('load', function() {
var email = '{!JSENCODE(Lead.Email)}';
var firstName = '{!JSENCODE(Lead.FirstName)}';
var lastName = '{!JSENCODE(Lead.LastName)}';
var fullName = '{!JSENCODE(Lead.Name)}';
var street = '{!JSENCODE(Lead.Street)}';
var city = '{!JSENCODE(Lead.City)}';
var state = '{!JSENCODE(Lead.State)}';
var zip = '{!JSENCODE(Lead.PostalCode)}';
var country = '{!JSENCODE(Lead.Country)}';
if (!firstName && fullName) {
var parts = fullName.trim().split(' ');
firstName = parts[0] || '';
lastName = parts.slice(1).join(' ') || '';
}
var d = btoa(JSON.stringify({ e: email }));
var ss = btoa(JSON.stringify({ e: email, fn: firstName, ln: lastName }));
document.getElementById('smartSendIframe').src =
'https://app.sendoso.com/m/send/smartsend?d=' + encodeURIComponent(d);
document.getElementById('marketplaceIframe').src =
'https://app.sendoso.com/m/manage/marketplace/readonly' +
'?recipientEmail=' + encodeURIComponent(email) +
'&recipientFirstName=' + encodeURIComponent(firstName) +
'&recipientLastName=' + encodeURIComponent(lastName) +
'&recipientAddress=' + encodeURIComponent(street) +
'&recipientCity=' + encodeURIComponent(city) +
'&recipientState=' + encodeURIComponent(state) +
'&recipientZip=' + encodeURIComponent(zip) +
'&recipientCountry=' + encodeURIComponent(country) +
'&ss=' + encodeURIComponent(ss);
});
</script>
<div id="tabBar">
<button class="customTab active" onclick="showTab('sends', this)">Send</button>
<button class="customTab" onclick="showTab('smartsend', this)">SmartSend</button>
<button class="customTab" onclick="showTab('marketplace', this)">Marketplace</button>
<button class="customTab" onclick="showTab('dashboard', this)">Dashboard</button>
</div>
<div id="tab-sends" class="tabContent active">
<iframe src="https://app.sendoso.com/v2/plugin/sends?channel=salesforce&name={!URLENCODE(Lead.Name)}&email={!URLENCODE(Lead.Email)}&company_name={!URLENCODE(Lead.Company)}&address={!URLENCODE(Lead.Street)}&city={!URLENCODE(Lead.City)}&state={!URLENCODE(Lead.State)}&zip={!URLENCODE(Lead.PostalCode)}&country={!URLENCODE(Lead.Country)}" scrolling="auto"></iframe>
</div>
<div id="tab-smartsend" class="tabContent">
<div class="smartsend-container">
<iframe id="smartSendIframe" src="" scrolling="auto"></iframe>
</div>
</div>
<div id="tab-marketplace" class="tabContent">
<div class="marketplace-container">
<iframe id="marketplaceIframe" src="" scrolling="auto"></iframe>
</div>
</div>
<div id="tab-dashboard" class="tabContent">
<div class="dashboard-container">
<iframe id="dashboardIframe" src="https://app.sendoso.com/m/dashboard" scrolling="auto"></iframe>
</div>
</div>
</apex:page>It should look something like this once done:
Lead
Contact
Next, navigate to the ‘Lightning App Builder’ and add a ‘New’ Lightning page:
Give your page a label and choose either the contact or lead object to add to:
Choose your page view either by cloning from an existing view or by choosing a page template. We recommend cloning from an SFDC existing page:
Add a tab to the page layout on the right-hand side and name it ‘Sendoso’ or ‘Send a Gift’:
You can also add a component to the left or right columns if preferred.
Add the ‘Visualforce’ component to the ‘Sendoso’ tab you created and set the height. Recommended height would be 600 px.
You can also adjust the height of the Sendoso window from the code block shown above.
Once added, assign the page to the specific profile(s) as needed:
And that’s it! Now on the Lead or Contact object, the necessary users should see the Sendoso tab and will be able to send directly from that tab.
Final version will look like this on the contact or lead object once complete:
Salesforce Lightning Component Setup
This guide walks through installing the Sendoso Tabs component in your Salesforce org entirely through your browser — no software installs or command line needed. The component adds a tabbed Sendoso panel (Send, SmartSend, Marketplace, Dashboard) directly on Contact and Lead record pages, pre-populated with the record's information.
Deploy the Component via Workbench
Workbench is a free, browser-based tool provided by Salesforce for deploying components.
Step 1 - Open Workbench
Go to https://workbench.developerforce.com and login to Salesforce
Click Deploy under the Migration tab at the top of the page. Upload the zip file attached to the bottom of this article named sendoso-lwc-deply.zip
Click Next at the bottom and then click Deploy at the bottom of the next page.
After a few seconds, you should see a confirmation page letting you know that it was successful.
⚠️ Note: If you see an error about an existing Aura bundle: Go to Salesforce Setup → Lightning Components → find and delete any component named sendosoTabs, then repeat Step 2.
Configure Salesforce Settings
Click here to see a step-by-step tutorial.
Step 2 - Add Trusted URLs
This step allows the Sendoso iframes to load inside Salesforce.
- In Salesforce, click the gear icon (top right) → Setup
- In the Quick Find search box (top left), type Trusted URLs and click it
- Click New Trusted URL — fill in the details below and click Save. Repeat 3 times:
| Field | Entry 1 — Sendoso App | Entry 2 — Google Fonts API | Entry 3 — Google Fonts Static |
| API Name | Sendoso_App | Google_Fonts_API | Google_Fonts_Static |
| URL | https://app.sendoso.com | https://fonts.googleapis.com | https://fonts.gstatic.com |
| Active | ✅ Checked | ✅ Checked | ✅ Checked |
| CSP Context | All | All | All |
| CSP Directives |
connect-src frame-src img-src |
font-src style-src |
font-src |
Add the Component to Record Pages
Step 3 - Add to Contact Record Pages
- Open any Contact record in Salesforce
- Click the gear icon (top right of the record page) → Edit Page
- In the left panel, scroll down to find sendosoTabs under custom components
- Drag the sendosoTabs component onto the page where you want it to appear
- Click Save (top right of the App Builder)
- Click Activate
- Select Assign as Org Default → click Save
Step 4 - Add to Lead Record Pages
- Open any Lead record in Salesforce
- Repeat steps 2–7 from Step 4 above
Tutorial
Check out the above steps in tutorial format!
Verify Everything Works
Open any Contact or Lead page, click the Sendoso tab and see all of the Sendoso tabs there! Here's what you should see:
Troubleshooting
| Problem | Solution |
| Grey screen / "Content is blocked" | Edit each Trusted URL in Setup and make sure the correct CSP directives are checked (see Step 3) |
| Component not showing in App Builder | Confirm the Workbench deploy succeeded with no errors (Step 2) |
| Workbench deploy fails with "Aura bundle" error | Go to Setup → Lightning Components → delete sendosoTabs → redeploy |
| Workbench shows "Invalid session" | Your Salesforce session timed out — go back to Step 1 and log in again |
| Marketplace tab shows grey screen | Contact your Sendoso representative — a feature flag may need to be enabled for your team |
| SmartSend tab shows grey screen | Contact your Sendoso representative — a feature flag may need to be enabled for your team |