Smart Capture form to show choices from a DE? - salesforce-marketing-cloud

I'm wondering if someone can possibly shed some light here, I have a smart capture form I'm building that has an add/update feature because of the primary key of "emailaddress"
I am pulling in the email address into a query string, which works great... the only thing though, is that I would like it to show a user's choice if they have already put in values into the DE previously.
For example here is the front end of the form, I would like it to show the choices a recipient already has before loading the page - similar to how it's pulling in their subscriber record. Is that possible? This page was built all with smart capture / cloud pages and a little ampscript to pull in their email address.
https://mcz5-l55x3kttqydms2vxt--5zkq.pub.sfmc-content.com/mrg20v12z2n?qs=ab0a1daabd536d524f3fc9c9356ad12470df153ed5fa9d014d7e7139de6192b957461dba656d17367648849aeb16d4db

Sounds like a preference center. You can look up values in the DE based on the email address you already have using the Lookup function. This assumes the email address variable is EmailAddress.
%%[
VAR #EventBooleanNullable2Value
SET #EventBooleanNullable2Value =
Lookup("[DE-NAME]","EventBoolean2Nullable","emailaddress", #EmailAddress)
]%%
And then in your HTML for the form you set the value of the input element like this below, assuming the values for the "EventBooleanNullable2" in the DE are true or false.
<input type="checkbox" name="EventBooleanNullable2" data-field-type="Boolean"
%%[IF #EventBooleanNullable2Value == "true" THEN]%%checked%%[ENDIF]%%>
https://ampscript.guide/lookup/

Related

currentDate in correspondence rule Pega

Currently working in Pega8.6.1, we want to put in an email(correspondence rule)/document a date field that shows a date plus 10 business days. The date should be 10 business days from the creation date of the email.
Have tried <%= pega_rules_datetime.pyCurrentDate.addDays("", 10, true, "") %> but am afraid I'm putting it wrong into the correspondence rule. In the generated email this formula is just shown as is.
Am fairly new with Pega so bear with me. Working now for about 2 months with Pega and afraid trying to reinvent the wheel.
Is what we are trying to establish even possible in Pega?
Thanks,
John
You can store the +10 days value in a separate property on Primary page of the email.
For example if pyWorkPage is your Primary page then you can have a separate property for example EmailPlusTen on pyWorkPage.
Then you can write something like below in a Data Transform or in an Activity rule before calling you email logic.
.EmailPlusTen = #(Pega-RULES:BusinessCalendar).addDays(#DateTime.CurrentDate("yyyyMMdd",""),10,true,"")
Then you can directly include property EmailPlusTen in your Correspondence rule by using this tag <<.EmailPlusTen>>
If you are using an activity to send the email then you can create a Parameter value and set it in the Activity before email logic.
for e.g.
Param.EmailPlusTen = #(Pega-RULES:BusinessCalendar).addDays(#DateTime.CurrentDate("yyyyMMdd",""),10,true,"")
And then include it in Email Correspondence <<Param.EmailPlusTen>>

How to prevent users from tampering HTML Form in the browser?

I have few checkboxes in my template whos value is the id of database row. I am using AJAX to post these values back and forth.
{% for item in sale_order_items %}
<tr>
<td class="text-center">
<input type="checkbox" name="saleorderitem" value="{{item.id}}">
</td>
</tr>
item.id for instance renders to 1. Now what if the user changes the value from 1 to 2 in browser using "inspect" and submits the form. what can I do at the frontend or django backend to prevent this and check if the user is submitting the same values as intended?
This depends on many different things but to take you back to the basics: When you create a function in order to bulletproof it out of any errors you use type and value checks.
I would think the best approach to this is to add some back-end checks. The form values returned would have to adhere a set of rule such as a value threshold. If the value returned is beyond that threshold then that would mean that something has changed in the HTML.
You add a check if it fails then the back-end would return an error. In collaboration with front-end you refresh the page and return an error message. It might be really terrible UX but an average end user would never change values using their inspector.
The other alternative is to use javascript to detect any kind of HTML/DOM mutations or changes which I would advice against. Having values to be checked against specific criteria (using the back-end) is best as it foolproofs info passed on to your server against any change.
I found a solution, in this scenario django session variable can be used to store data between requests. When I load the form, I set the session variable to the required values, then on form submission, I check the submitted values with the values in session variable. And it works.

ContactsApp.getContact() for contact with multiple emails returns a different contact for each email address

My company allows employees to have multiple email addresses in their account.
I am attempting to write an input form where someone can enter any of the emails for a contact and we'll resolve it to the same person.
I've tried doing this via ContactsApp.getContact(email).getPrimaryEmail() to resolve all different inputs to the same primary email, but it doesn't work as expected. Each email I search for returns a different Contact object with only a single email (the one I used to search).
Even if I use ContactsApp.getContact(email).getEmails() to list all emails to the employee, I can see it only returns one at a time.
When going to contacts.google.com, I see the information I expected. Searching for any of the emails will return the same contact, with the same primary email and all other emails listed.
Is there something I'm doing wrong? Or is this how ContactsApp works. If so, is there a workaround?
Thanks!
getPrimaryEmail() will only return an email address if the contact in question has had a default email set and this can only be done via the Google Contacts App, not on the web (go figure).
To solve your problem I would suggest loading all the contacts into an array variable first and then searching this for matching email addresses. I would do the data retrieval on page/view load (so it can be reused without multiple server calls) but have included it all together here for conciseness.
What I found strange about the ContactsApp (and presumable People API too) is that the contacts returned are just empty objects (when logged) with just a bunch of methods on them. However, once you have an array of objects you can write your own properties to those objects for easier access of data.
Therefore I would first of all retrieve all the users contacts, then add a property of .emails to each contact object in the array and then use .some, perhaps, to check if a match appears in .emails (which will also be an array).
Something like:
let strSearch = 'someone#somewhere.net' // EMAIL address to search based on user input
let arrContacts = ContactsApp.getContacts();
let contacts = arrContacts.map(contact => {
let emails = contact.getEmails();
contact.emails = emails.map(email => email.getAddress());
return contact;
});
let foundContact = contacts.filter(contact => contact.emails.some(email => email === strSearch));
Remember .getEmails() returns another array of objects that have the method .getAddress() on them in order to retrieve the actual address, that's why I'm getting an array of email objects with let emails = contact.getEmails(); then using emails.map here to put the actual email addresses into an array stored in the contact.emails property (that doesn't exist so we're actually creating it here).
After that we're filtering the contacts array down to a contact where the searched email address is matched to one of the email addresses in the contact.emails array. I haven't tested it so the last line might need playing around with slightly but I've used something very similar so would expect it to work.
You can then use foundContact[0] to reference the contact found and use the further methods of .getFullname() .getId() etc. to retrieve their data as required. If you need the contacts phone numbers or geographical address that's a whole other process of returning an array of objects using .getPhones() or getAddresses(), but I think that's beyond the scope of this question.

"Create or update" form behavior when hitting back button

I have the following workflow on a website:
Some user John Doe declares a company through form 1
(fields: name, head office location)
After John Doe submits (HTTP POST) form 1, he is redirected (HTTP 302) to company form 2 with additional legal information about the company.
The problem is, if John Doe hits the back button of his browser during step 2, he will land on the form 1, with data filled by the browser (using values he already submitted — that's what Firefox and major browsers seem to do).
John Doe might then think he can use this form to update some information (e.g. fix a typo in the name of the company) whereas he will actually create a new company doing so, as we don't know on the server side whether he wants to declare a new company or update the one he just created.
Do you know any simple solution to handle that problem ?
Use javascript/jquery script after the page is loaded to empty all the inputs. This will prevent confusion of "updating the company".
jQuery would look something like this:
$('#elementID').val('');
You can also handle the situation by manipulating the browser history
on load of form 2, and pass the CompanyId generated on submit of form 1 using querystring. So that you can actually update the company as the user
Suppose John submits form1.html, a unique CompanyId "1001" is generated and redirected to form2.html. Now on load of form2 you can modify the browser history form1.html?companyid=1001 using
var stateObj = { foo: "bar" };
history.pushState(stateObj, "page 1", "form1.html?companyid=1001");
Now, when the user click back button and submits the form1 again. you can check for companyid in querystring and update the company.
I think it is more user-friendly when user can return back to previous form and update it (instead preventing the described behavior).
I use in most cases similar way to handle described problem:
Let's assume that user is on the page /some-page, that contains "Create new company" button.
When the user opens this page, will be executed special method createOrFindCompanyDraft() on the server-side. This method creates new company "draft" record in DB (only for the current user). For example, draft record has primary key id=473. When you execute this method again it will return the same record with the id=473 (with "draft" status). "Draft" record should't display on any other interfaces.
And "Create new company" has link /company/common/473.
When user go to /company/common/473, you display form 1, that will be filled from "draft" record. At first time user will see empty form.
Technically user will update the existing record, but you can display "Create new company" title on the page.
Then user go to form 2, for example, /company/legal-info/473, you create similar draft record for the this form (similar to step 1).
When user submit the form 2, you will remove "draft" status from the record id=473 (and any related records).
Next time when user open page /some-page, will be created new draft record for the current user.
Browser history will contain:
/some-page
/company/common/473
/company/legal-info/473
/some-page2
I like this approach, because all form only update records. You can go to previous/next form many times (for example "Back"/"Forward" browser buttons). You can close browser, and open not completed forms tomorrow. This way doesn't require any additional manipulation with the browser history.
try this
<form autocomplete="off" ...></form>
And Another
Use temporary tables or session to store the Page 1 form data. If the page 2 form is submitted use the temporary data of page 1 which is stored in database or in session.
Use a Separate key (Hidden field ) in both page 1 and page 2.
Actually I thought of a trick to obtain that "create on first post, update after" behavior (just like the user thinks it should behave).
Let's say the step 1 form is at the URL /create_company/. Then I could have that page generate a random code XXX and redirect to /create_company/?token=XXX. When I create the company I save the information that it was created through page with token XXX (for instance, I save it in user's session as we don't need to keep that information forever) and when the form is submitted, if I know that a company was already generated using this token, I know the user used the same form instance and must have used the back button since the token would be different if he explicitly asked for another company.
What do you think ? (I initially thought there should be a simpler solution, as this seems a little bit over-engineered for such a simple issue)
This is more like a UX question.
I'd think that the solution lies within the information given to the user on that form, to help them understand what they're doing.
Set a title that says 'Create a company', for example, and set your submit button as 'Create Company' will help your user with that. Use a unique id when you create the company object, and pass the id back to the same URL in order to perform an update. You should then update your title and button that tells user that they are updating instead of creating.
In that sense I'd say it's better to use a more generic URL like /company and /company?id=12345.
You could also consider using Restful API protocol to help your server identifies the CRUD operation. http://www.restapitutorial.com/lessons/httpmethods.html
Without the "routing" part of django it is hard to help. I can just answer my experience from the express.js-router functionality:
you can specify a post on /company, which is for new users.
you can specify another route for post on /company/:companyid for a changing form
and as a response from the create-post you can redirect to the different location.

MS Access 2010- How to update field on one table based on field in another table

I'm designing a database to track requests. Currently, I have a form that its' record source is based off a query "Unassigned Requests". This query is based off my table Requests, and returns all "unassigned Requests". In this form, I would like the status field to change to "Assigned", once a Tech field has been assigned to the request. I currently have the Default for the Tech Assigned field set to "Blank', and the status field set to 'Unassigned". Both of these fields are combo boxes. The status field has a control source from the request table and row source from the status table. The tech assigned field has a control source from the Tech table and the row source is based off a query.
I have tried multiple solutions that have not seemed to work. I have limited experience with Macros and VBA. I would appreciate any suggestions on solving this problem.
I am going to make some assumptions regarding your post and if any are incorrect please let me know.
You have a request form where a request is assigned to a Tech. On that form there is a dropdown for the status, and also for the Tech.
You want to make it so when the tech dropdown is filled out with a tech's name you want the dropdown to change to assigned.
If this is the case I would recommend using the Tech Assigned field's AfterUpdate event. The code would look something like this:
Private Sub cboTech_Assigned_AfterUpdate()
If Nz(Me.cboTech_Assigned.Value, "") <> "" Then
Me.cboStatus = "Assigned"
Else
Me.cboStatus = ""
End If
End Sub
Obviously you will need to adjust to your own naming scheme. I should also point out that I don't even know if that Nz function is needed, I have just gotten into the habit of putting it everywhere. If I misunderstood something about what you want to do please let me know!