PF Enterprise FAQ

Common questions about setting up and maintaining a PF Enterprise site.


Umbraco & FTP Access

Umbraco: https://pages.photofinale.com/umbraco/
FTP: ftp://ftp.photofinale.com:990  (Secure FTP)

Your credentials will be provided by your account manager.


Custom Media

Your FTP account gives you access to your site's custom media directory.  You can store any external content here that you wish to use in your site – JPG, PNG, CSS, JS, PDF, MP4, ZIP, TTF, OTF, WOFF, etc.  You link to content in your media directory by simply using the relative path, /media.  For example, if you create a folder in your media folder called "images" and place a file called "logo.png", you would access it with an <img> tag source of "/media/images/logo.png".


Content Cache

Changes to content made within Umbraco or to files in your FTP directory can take some time to show up on the site due to caching.


Type

Cache Duration

Changes to Umbraco Content

Up to 30 Minutes

Changes to FTP Content

Up to 10 Minutes


To facilitate development, you can point your browser to our sandbox server, which only caches Umbraco content for 1 minute. This makes rapid-fire change-and-test cycles much easier.

You can hit the sandbox version of your site at any time by using the address: https://*yoursitename*.pfsandbox.com.


Page Versions

Each content page (aka "landing page") that you create in Umbraco has a version setting:
 

The version determines which page host the custom content will be embedded within when rendered on your PF site.

Version 9 pages are hosted in our traditional jQuery UI-backed page host.

Version 10 pages are hosted with our newer, HTML5, responsive, Bootstrap-backed page host.

We recommend that all new Umbraco pages be created for Version 10, so that they are optimized for all viewing platforms – desktop, tablet and mobile.


PageParts

The site splits pages into several individual components so that common pieces can be shared across the whole site.  These common pieces are called "PageParts".   



Each PagePart has a traditional and "mobile" version.  In this case, the term "mobile" really connotes "responsive".  Mobile pages are built with around a responsive, Bootstrap-enabled page framework that can be used with all modern browsers – desktop, tablet and mobile.  The mobile version of each PagePart is denoted with a "-mobile" suffix.

The traditional PagePart version is used on all legacy pages of the site (Silverlight workflow & original checkout pages) while the mobile version is used on the newer, HTML5, Bootstrap-enabled pages.

As of October 2016, the Silverlight workflows have been deprecated and 95% of the site runs off of the newer, HTML5, Bootstrap pages.
As of July 2017, we no longer recommend that you maintain both sets of PageParts. Going forward, for new and existing sites only the "-mobile" versions are required.


A description of the five available PageParts: 

PagePartDescription
HtmlHeadIncludeIncluded in the <HEAD> section of the HTML document. Useful for setting <meta> tags, linking to stylesheets, etc.
HeaderBodyThe header shown on every page of the site.
FooterBodyThe footer shown at the bottom of every page on the site.
FooterExtraInserted underneath the footer, typically the very bottom of the HTML document. Useful place to stick 3rd-party scripts, to minimize their impact on the page load time.
ConfirmationExtraAdded to the body of the order confirmation page, allowing you to display additional content specific to your store or add 3rd-party scripts which track order


CSS Styling

We strongly recommend that you provide an appropriate css namespace scope for your styles to ensure they do not conflict with the default Photo Finale styling.

In practice, this simply means placing all of your custom content in a <div> with a unique parent class name, for example:

<div class="dealer-name">

[ CUSTOM CONTENT ]

</div>

Then each style defined in your CSS file should use that parent selector to define the styles. Setting the font-size of the <legend> element, for example will look like:

.dealer-name legend {
      font-size: 16px;
}

Your style sheets will always be included after the default Photo Finale style sheets, so it is therefore possible for you to override any of the default PF styling by omitting the .dealer-name scope, for example:

legend {
      font-size: 16px;
}

We recommend against overriding the default Photo Finale styling, except as noted below. Photo Finale cannot take responsibility nor provide engineering resources to help diagnose or debug problems caused by overrides to the default styles. Ensuring that the default styling is compatible with all supported browsers on OS X and Windows is enough fun for us already!


Most PF Enterprise sites will need to override certain PF layout styles, shown here. The values of the #header.pageLayout height and #content.fullpage top should be the same and should represent the actual height of your header content.

/* Photo Finale Overrides */

#pageWrapper {
      background: none;
      box-shadow: none;
      max-width: 100%;
}

#header {
      background: none;
      height: 78px;
      border: none;
}

.fullpage #content {
      top: 78px;
}

#footer {
      background: none;
}


Creating Pages

Your site can have as many custom pages as you care to build.  These page are often referred to as "marketing pages", "landing pages", or "Umbraco pages".

You have control over the page hierarchy which dictates the URL.  To determine the URL for a page, simply append the folder path to your site domain, following these substitution rules:

  • Strip all non-alphanumeric characters except for hypen and period
  • Convert any spaces to a hypen
  • Convert any & characters to "and"

Example:

PATH: / example folder / subfolder! / page with & in the name

URL: /example-folder/subfolder/page-with-and-in-the-name 

To create pages and folders, simply click on the "..." icon at the level you wish to insert from and then choose to insert either a folder or a page.

NOTE

Content pages can have subpages. Therefore the only difference between a folder and a content page is that if the user hits a URL for a folder itself, they will get a 404 error since there is no content. For that reason we recommend using content pages instead of folder in virtually all circumstances.


Reserved Page Names

The following names are reserved by Photo Finale and should not be used as page or folder names within Umbraco. This list may change from time to time.

  • account
  • addphotos
  • ccvinfo
  • changepassword
  • checkout
  • confirmation
  • create
  • default
  • feedback
  • forgotpassword
  • get
  • getstarted
  • gift
  • gifts
  • guest
  • help
  • home
  • link
  • members
  • membershipinfo
  • migrateuser
  • mobile
  • mycart
  • mycollections
  • myfeeds
  • myorders
  • myphotos
  • orderhistory
  • optout
  • photo
  • photos
  • photofeed
  • platform
  • prepaidplans
  • pricelist
  • print
  • prints
  • projects
  • share
  • shop
  • signin
  • signout
  • signup
  • signupcomplete
  • startsharing
  • stores
  • terms
  • trackmyorder
  • trackorder
  • transferconten
  • unsubscribe
  • upgrade
  • user


Invalid Page Name Characters

These characters may not be used in an Umbraco page name:

  • '
  • "
  • !
  • %
  • .
  • ;
  • /
  • \
  • :
  • #
  • +
  • *
  • &
  • ?
  • >
  • <
  • _

JavaScript Libraries

Photo Finale includes a number of JS libraries. Umbraco content that includes these same libraries (or different versions of them) will likely cause conflicts and should be avoided.  Please use the View Source feature in your browser to check which libraries/versions are being included.


JavaScript Client Objects

PF Enterprise provides a JavaScript object ("PF") this is available to be used in Umbraco pages and PageParts.

General Data Members

PF.dealer.name = "Silverline Demo Lab";
PF.dealer.code = "9071";
PF.dealer.country = "US";
PF.dealer.currencyCode = "USD";
PF.dealer.currencySumbol = "$";
PF.dealer.email = "lab@silverlinephoto.com";
PF.dealer.phone = "703-564-3400";
PF.user.isAuthenticated = false;
PF.region = 'en-US';
PF.cultureInfo.name = 'en-US';
PF.cultureInfo.displayName = "English (US)";
PF.domain = 'https://silverline.photofinale.com';
PF.authenticationUrl = 'https://silverline.photofinale.com/signin';
PF.basketId = "2d036975-c2e3-48f3-8c22-7b7f631e631e";

On the order confirmation page, an orderSummary object is also available:

Order Data Members (only available in the ConfirmationExtra PagePart)

PF.orderSummary.confirmation : int
PF.orderSummary.subTotal : number
PF.orderSummary.discount : number
PF.orderSummary.tax : number
PF.orderSummary.shipping : number
PF.orderSummary.total : number
PF.orderSummary.balanceDue.valueOf() : number

PF.orderSummary.items : array
PF.orderSummary.items[0].productId : int
PF.orderSummary.items[0].productName : string
PF.orderSummary.items[0].quantity : int
PF.orderSummary.items[0].price : number

PF.orderSummary.coupons : array
PF.orderSummary.coupons[0] : string


Integrating with 3rd-Party Shopping Cart Tracking Scripts 

In order to register order completion with 3rd-party shopping cart tracking scripts, the ConfirmationExtra-mobile PagePart can be used.  Within that PagePart, the PF.orderSummary object described above will be available for use.

If a 3rd-party integration includes a call to load an external script, that script will be loaded asynchronously meaning that any JS commands you place immediately afterwards may run before the script is actually loaded.

Loading a 3rd-Party Script
<script type=text/javascript" src="//www.some-shopping-cart-tracker.com/script.js"></script>


To combat this, you may need to wrap the subsequent integration code into an anonymous function that waits until the objects from the 3rd-party script are loaded and available to be used. 


Here's an example that creates an anonymous function to check for the existence of the 3rd-party tracker's object ("MyTracker" in our example) and then calls the fictitious "TrackOrder" method passing along the order # and total.

Wait For 3rd-Party Script Before Using It
( function _trackerScript() {
                if (typeof (MyTracker) == "undefined") {
                    setTimeout(function () { _trackerScript(); }, 500);
                } else {
                    MyTracker.TrackOrder(PF.orderSummary.confirmation, PF.orderSummary.total);
                }
   })();


Page Transition Events

Since the Photo Finale site is a Single Page Application (SPA), there aren't traditional page fetches from the server as the user nagivates the site.  If you wish to attach code to a particular page, you need to listen for the $pf-url-visited event and use the url parameter to identify the page the user has navigated to.  For example:

<script type="text/javascript">
	$(document).on("$pf-url-visited", function (event, url)
	{
		console.log(url);
	});
</script>


Language Selection

The Photo Finale Web platform is currently localized into French, Spanish, Italian, Finish, Norwegian, Swedish and Japanese.  The site is designed to automatically select the most appropriate language based on the user's operating system locale settings when they first visit the site.  However, it is a good idea to also provide a language selector on the page, often placed in the site footer.  Once a user selects a language, that choice is stored in a cookie and will be utilized on future visits to the site.

To add your own, stylizable, language selector to your site you can use: 

<li><select id="language-selector"></select></li>
 
<script type="text/javascript">
	$(function() {
		PF.ui.languageSelect("#language-selector");
	});
</script>


Alternatively, you can utilize our default language selector on your custom page by using:

<language-selector dropup="true/false"></language-selector>


You can force a user into a particular language by calling:

<script type="text/javascript">
	PF.ui.setLanguage('fr-CA');
</script>


Overriding Platform Strings

Version 17.1 introduced the capability for individual language strings within the platform to be overridden by a dealer site.  Configuration must be.  Begin by preparing a JSON object containing the strings you wish to override.  This can include overrides in multiple languages, if desired.  For example:

{
  "en-US": {
    "SignIn_RememberMeLabel": "Don’t you dare forget me!",
    "SignIn_Incorrect": "Nope! Try again."
  },
  "fr-CA": {
    "SignIn_RememberMeLabel": "N'ose pas m'oublier !",
    "SignIn_Incorrect": "Non! Essayer à nouveau."
  }
}

The string ID (e.g. "SignIn_Incorrect") can be found in the attached list of platform strings: i18n-overrides-2024-03-15.json

Once the string override JSON has been prepared, deliver it to your account representative for them to load into the platform.


Scheduling Page Publishes

COMPATABILITY ISSUE

Due to a compatibility issue with recent versions of Umbraco, the Scheduled Publish feature is currently broken.  Until this issue is resolved in a future PF Web release, do not schedule a future publish.

It is possible to schedule the publishing of a new page or update to an existing page for a future date/time.

  1. On the Properties tab of the page, set a value in the "Publish at" field.  The time should be specified for US Eastern Time.
  2. Rather than hitting the normal Save and publish button, instead click on the arrow next to the button and choose to Save only.


Note

Due to local caching on the web servers, changes may not propagate to all web servers for up to 30 minutes from the time scheduled in Umbraco.


Tips

  • Put a ‘My Projects’ button in even for anonymous users. For anonymous users, they are stored via cookies, just like the anonymous user's shopping cart. 
  • Use relative links. Relative links are best.
  • Linking to products/groups. For the best SEO and future-proofing, always use links to products and categories as shown in the Web Links page of myLab.
  • Newsletter signup.  html can’t have a <form> within a <form>. The site is already wrapped in a <form> so any others get tossed out. The submit would need to be scripted or pop something up.