So You Only Want Intercom Chat On Certain Pages In WordPress? Here’s How!

So I had a client want to use Intercom. Great! So I went to Intercom and signed up for an account, then went to our WordPress instance and downloaded the Intercom for WordPress plugin. Everybody wins! Until…I get the requirement after the fact that the client does not want the chat pop up on every page…but only on certain pages. However, the out of the box Intercom for WordPress plugin is only built to be supported for all pages and not some. What to do…what to do…let’s figure it out.

First, login into your WordPress (.org version) as an admin and uninstall the Intercom for WordPress plugin. Next install the Head, Footer and Post Injections Plugin:

Once installed, go to the Head, Footer and Post Injections plugin settings and insert the following script injection into the Desktop and Mobile (Check the Mobile checkbox) BEFORE THE CLOSING TAG (FOOTER). 

<script>
var ref1= window.location.pathname;
var search1 = "/pagepath1/";
var search2 = "/pagepath2/"; 
if (ref1.indexOf(search1) > -1 || ref1.indexOf(search2) > -1)
  window.intercomSettings = {
    app_id: "YourIntercomID"
  };
</script>
<script>(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',intercomSettings);}else{var d=document;var i=function(){i.c(arguments)};i.q=[];i.c=function(args){i.q.push(args)};w.Intercom=i;function l(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/nna8fbly';var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);}if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})()</script>

Save the plugin settings. This JavaScript will check on the specified page paths and only execute turning on Intercom for the specific page paths. Hope this helps!

Solved: Issue with SharePoint Rest API Document Upload – Solving the case of the single apostrophe/quote in the URL POST

So I ran across an interesting mystery a while back that I thought I would share the fix for once I had time to document it. I have a client that uses an embeddable SharePoint page within CRM to allow document uploads right from the front entity screens without having to deviate to another screen and for the most part things have been going well. Until…the mystery began.

The problem: In some sporadic cases when uploading documents via POST to the REST API users would encounter an issue with the dynamically generated URLs from SharePoint that contain single apostrophes or quotes in the library name that would be used in the POST URL.

Errors may look like:

{"error":{code":"-1,Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":en-US","value":"The expression\"web/getfolderbyserverrelativeurl('yourfolder/O'Lastname, Firstname - 23424ID')/files/add(overwrite=true,url='filename.pdf')\" is not valid."}}}

The odd part about that? If you browse the library on its own, it’s fine! However, trying to post to the REST API with an improperly escape quote is not. So let’s fix that.

The solution: It’s all in how you build the URL with properly escaped characters.

Snippet in question:

    // Add the file to the file collection in the Shared Documents folder.
    function addFileToFolder(arrayBuffer) {

        // Get the file name from the file input control on the page.
        var parts = fileInput[0].value.split('\\');
        var fileName = parts[parts.length - 1];

        // Construct the endpoint.
        var fileCollectionEndpoint = String.format(
                "{0}/_api/web/getfolderbyserverrelativeurl('{1}')/files" +
                "/add(overwrite=true, url='{2}')",
                serverUrl, serverRelativeUrlToFolder, fileName);

        // Send the request and return the response.
        // This call returns the SharePoint file.
        return jQuery.ajax({
            url: fileCollectionEndpoint,
            type: "POST",
            data: arrayBuffer,
            processData: false,
            headers: {
                "accept": "application/json;odata=verbose",
                "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
                "content-length": arrayBuffer.byteLength
            }
        });

Fixed snippet:

    // Add the file to the file collection in the Shared Documents folder.
    function addFileToFolder(arrayBuffer) {

        // Get the file name from the file input control on the page.
        var parts = fileInput[0].value.split('\\');
        var fileName = parts[parts.length - 1];

        // Construct the endpoint.
        var fileCollectionEndpoint = String.format(
                "{0}/_api/web/getfolderbyserverrelativeurl('{1}')/files" +
                "/add(overwrite=true, url='{2}')",
                serverUrl, serverRelativeUrlToFolder.replace(/\%27/g,"''"), fileName);

        // Send the request and return the response.
        // This call returns the SharePoint file.
        return jQuery.ajax({
            url: fileCollectionEndpoint,
            type: "POST",
            data: arrayBuffer,
            processData: false,
            headers: {
                "accept": "application/json;odata=verbose",
                "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
                "content-length": arrayBuffer.byteLength
            }
        });

Conclusion? With the replace regex fix in place it will now take every occurance (and not just the first, thanks regex) of a single quote that come as a part of the folder directory and properly escape them when I want to post a file back with the API.

Key change:

serverRelativeUrlToFolder.replace(/\%27/g,"''")

Everybody wins now, espcially the people out there with apostrophes in there names and folder names with titles that still need the quotes in them! Hope this helps.

References:

Solved: The length of the URL for this request exceeds the configured maxUrlLength value.

Anyone ever run into the following before? I ran into this regarding a request into the SharePoint Rest API.

The length of the URL for this request exceeds the configured maxUrlLength value.

This because the IIS default maximum length for an URL is 260 characters. If a URL request is longer, the above error will occur.

To fix this you can increase the maxURLlength value, add it to your web.config file in the IIS virtual Directory.

<configuration>

  <system.web>

    <httpRuntime maxUrlLength="5000" />

  </system.web>

</configuration>

It will be likely you will already have most of this snippet in place so don’t break your config; just add the maxUrlLength property into your existing httpRuntime section and you should be good to go. Do know any web.config changes may cause a service interruption so test in dev, beta, QA and pre-prod before ever changing in prod! Hope this helps, questions are welcome!

Solved: Method not found: ‘!!0[] System.Array.Empty()’.

If you are getting a message for your recently developed .Net application when you publish to the server to the effect of:

ssnetframeworkerror

Chances are the server you are deploying to does not have the appropriate framework to support your app.

Download the Microsoft .Net Framework 4.6.1 and install it to resolve this. It will likely require a server reboot to complete it so don’t do it on prod mid-day! Hope this helps, questions are welcome!

Example of a JIRA Priority/Work Estimate/Role Matrix

So as I work to help standardize how the teams I work with estimate effort on their projects I have worked through leveraging JIRA to better help clarify what the priority field could mean. We work in a space where when items go beyond a certain amount of hours that we want to switch from a developer role into a consultant/management role.

matrix

If you would like a file with it instead you can get that here. Hope this helps!

Ready to send email in Amazon SES? Let’s Go!

First, consult with AWS and get your credentials:

http://docs.aws.amazon.com/ses/latest/DeveloperGuide/using-credentials.html
and
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-using-smtp-net.html

Secondly, let’s make a more easily updatable emailSettings section (encrypt it later, see here if you need help):

  <appSettings>
    <add key="MailFrom" value="donotreply@youremaildomain.com"/>
    <add key="MailTo" value="whoareyousendingto@theiremaildomain.com"/>
    <add key="MailHost" value="	email-smtp.youramazonseshost.com"/>
    <add key="MailPort" value="587"/>
    <add key="MailServerUserName" value="awsSESusername"/>
    <add key="MailServerPassword" value="awsSESpassword"/>
  </appSettings>

Then, include the reference:

	using System.Net.Mail;		

Finally, write your method:

	public static void sendEmail(string to, string from, string subject, string body)
	{
		try
		{
			// Initialize client and message
			using (SmtpClient mailclient = new SmtpClient(ConfigurationManager.AppSettings["MailHost"].ToString(), Convert.ToInt32(ConfigurationManager.AppSettings["MailPort"])))
			{
				// Create message
				mailclient.UseDefaultCredentials = false;
				mailclient.EnableSsl = true;
				mailclient.Credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["MailServerUserName"].ToString(), ConfigurationManager.AppSettings["MailServerPassword"].ToString());
				MailMessage message = new MailMessage(from, to);
				message.Subject = subject;
				message.Body = body;
				message.IsBodyHtml = true;
				mailclient.Send(message);
			}
		}
		catch (SmtpException ex)
		{                
			// Service was not available to send message keep trying
			if (ex.StatusCode.Equals(SmtpStatusCode.ServiceNotAvailable))
			{
				sendEmail(to, from, subject, body);
			}
		}
	}

Great! Now you can call it and send an email

string htmlBody = "<b>Hi! It's my message</b>";
sendEmail(ConfigurationManager.AppSettings["MailTo"].ToString(), ConfigurationManager.AppSettings["MailFrom"].ToString(), "Your Email Subject", htmlBody); 

You can always put whoever and whatever when you call the method using To, From, Subject and Body.

Enjoy! Questions are welcome.

SharePoint/PowerShell – Get the AD groups associated with a site collection and output to CSV file

Need to deliver or better understand the AD groups associated with your SharePoint site collection? Try this:

$SPWebApp = Get-SPWebApplication http://sitecollectionURLhere/

foreach ($SPSite in $SPWebApp.Sites)
{
    write-host -foregroundcolor green "Working on Site Collection: " + $SPsite.RootWeb.Title 
    $SiteURL = $SPsite.RootWeb.URL
    $ADgroup=Get-SPUser -Web $SiteURL -Limit ALL | Where { $_.IsDomainGroup }
}
echo $ADgroup | Export-Csv "C:\Temp\FileNameGoesHere.csv"

PS1 download is here: https://1drv.ms/u/s!Ag4C3w6EUQIggowvfXrE0Z3tfWKJeA