text:
project_path: /web/_project.yaml
book_path: /web/updates/_book.yaml
description: The Device Memory API allows developers to serve different resources to users based on their device's memory capabilities.

{# wf_updated_on: 2019-10-13 #}
{# wf_published_on: 2017-12-07 #}
{# wf_tags: performance #}
{# wf_blink_components: Blink>PerformanceAPIs #}
{# wf_featured_image: /web/updates/images/generic/devices.png #}
{# wf_featured_snippet: The Device Memory API allows developers to serve different resources to users based on their device's memory capabilities. #}

# The Device Memory API {: .page-title }

{% include "web/_shared/contributors/philipwalton.html" %}

The range of capabilities of devices that can connect to the web is wider today
than it's ever been before. The same web application that's served to a high-end
desktop computer may also be served to a low-powered phone, watch, or tablet,
and it can be incredibly challenging to create compelling experiences that work
seamlessly on any device.

The[ Device Memory API](https://github.com/w3c/device-memory) is a new web
platform feature aimed at helping web developers deal with the modern device
landscape. It adds a read-only property to the `navigator` object,
`navigator.deviceMemory`, which returns how much RAM the device has in
gigabytes, rounded down to the nearest power of two. The API also features a
[Client Hints Header](/web/updates/2015/09/automating-resource-selection-with-client-hints),
`Device-Memory`, that reports the same value.

  Note: The JavaScript API is new in Chrome 63, while the
  Client Hints header has been enabled by default in Chrome since version 61.

The Device Memory API gives developers the ability to do two primary things:

* Make runtime decisions about what resources to serve based on the returned
  device memory value (e.g. serve a "lite" version of an app to users on
  low-memory devices).
* Report this value to an analytics service so you can better understand how
  device memory correlates with user behavior, conversions, or other metrics
  important to your business.

## Tailoring content dynamically based on device memory

If you're running your own web server and are able to modify the logic that
serves resources, you can conditionally respond to requests that contain the
`Device-Memory` [Client Hints Header](
/web/updates/2015/09/automating-resource-selection-with-client-hints).

```
GET /main.js HTTP/1.1
Host: www.example.com
Device-Memory: 0.5
Accept: */*
```

With this technique, you can create one or more versions of your application
script(s) and respond to requests from the client conditionally based on the
value set in the `Device-Memory` header. These versions don't need to contain
completely different code (as that's harder to maintain). Most of the time, the
"lite" version will just exclude features that may be expensive and not critical
to the user experience.

### Using the Client Hints Header

To enable the `Device-Memory` header, either add the Client Hints `<meta>` tag
to the `<head>` of your document:

```
<meta http-equiv="Accept-CH" content="Device-Memory">
```

Or include "Device-Memory" in your server's `Accept-CH` response headers:

HTTP/1.1 200 OK
Date: Thu Dec 07 2017 11:44:31 GMT
Content-Type: text/html
Accept-CH: Device-Memory, Downlink, Viewport-Width

This tells the browser to send the `Device-Memory` header with all sub-resource
requests for the current page.

In other words, once you've implemented one of the options above for your
website, if a user visits on a device with 0.5 GB of RAM, all image, CSS, and
JavaScript requests from this page will include the `Device-Memory` header with
the value set to "0.5", and your server can respond to such requests however you
see fit.

For example, the following [Express](http://expressjs.com/) route serves a
"lite" version of a script if the `Device-Memory` header is set and its value is
less than 1, or it serves a "full" version if the browser doesn't support the
`Device-Memory` header or the value is 1 or greater:

```
app.get('/static/js/:scriptId', (req, res) => {
  // Low-memory devices should load the "lite" version of the component.
  // The logic below will set `scriptVersion` to "lite" if (and only if)
  // `Device-Memory` isn't undefined and returns a number less than 1.
  const scriptVersion = req.get('Device-Memory') < 1 ? 'lite' : 'full';

  // Respond with the file based on `scriptVersion` above.
  res.sendFile(`./path/to/${req.params.scriptId}.${scriptVersion}.js`);
});
```

  Note:
  The Accept-CH header works well for a page's subresource, but it
  doesn't help if you want to conditionally serve page contents based on device
  capabilities. To address this, the
  Accept-CH-Lifetime header (coming soon to Chrome) instructs
  browsers to include the specified client hints headers in all subsequent
  requests from this origin for the number of seconds specified by the header
  value.

### Using the JavaScript API

In some cases (like with a static file server or a CDN) you won't be able to
conditionally respond to requests based on an HTTP header. In these cases you
can use the JavaScript API to make conditional requests in your JavaScript code.

The following logic is similar to the Express route above, except it dynamically
determines the script URL in the client-side logic:

```
// Low-memory devices should load the "lite" version of the component.
// The logic below will set `componentVersion` to "lite" if (and only if)
// deviceMemory isn't undefined and returns a number less than 1.
const componentVersion = navigator.deviceMemory < 1 ? 'lite' : 'full';

const component = await import(`path/to/component.${componentVersion}.js`);
component.init();
```

While conditionally serving different versions of the same component based on
device capabilities is a good strategy, sometimes it can be even better to not
serve a component at all.

In many cases, components are purely enhancements. They add some nice touches to
the experience, but they aren't required for the app's core functionality. In
these cases, it may be wise to not load such components in the first place.
If a component intended to improve the user experience makes the app sluggish
or unresponsive, it's not achieving its goal.

With any decision you make that affects the user experience, it's critical you
measure its impact. It's also critical that you have a clear picture of how your
app performs today.

Understanding how device memory correlates with user behavior for the current
version of your app will better inform what action needs to be taken, and it'll
give you a baseline against which you can measure the success of future changes.

## Tracking device memory with analytics

The Device Memory API is new, and most analytics providers are not tracking it
by default. Fortunately, most analytics providers give you a way to track custom
data (for example, Google Analytics has a feature called [Custom
Dimensions](https://support.google.com/analytics/answer/2709828)), that you can
use to track device memory for you users' devices.

### Using a custom device memory dimension

Using custom dimensions in Google Analytics is a two-step process.

1. [Set up the custom dimension](
   https://support.google.com/analytics/answer/2709829) in Google Analytics.
2. Update your tracking code to [`set`](
   /analytics/devguides/collection/analyticsjs/accessing-trackers)
   the device memory value for the custom dimension you just created.

When creating the custom dimension, give it the name "Device Memory" and choose
a [scope](https://support.google.com/analytics/answer/2709828) of "session"
since the value will not change during the course of a user's browsing session:

Next update your tracking code. Here's an example of what it might look like.
Note that for browsers that don't support the Device Memory API, the dimension
value will be "(not set)".

```
// Create the tracker from your tracking ID.
// Replace "UA-XXXXX-Y" with your Google Analytics tracking ID.
ga('create', 'UA-XXXXX-Y', 'auto');

// Set the device memory value as a custom dimension on the tracker.
// This will ensure it gets sent with all future data to Google Analytics.
// Note: replace "XX" with the index of the custom dimension you created
// in the Google Analytics admin.
ga('set', 'dimensionXX', navigator.deviceMemory || '(not set)');

// Do any other other custom setup you want...

// Send the initial pageview.
ga('send', 'pageview');
```

### Reporting on Device Memory data

Once the device memory dimension is
[`set`](/analytics/devguides/collection/analyticsjs/accessing-trackers) on the
tracker object, all data you send to Google Analytics will include this value.
This will allow you to break down any metric you want (e.g. [page load
times](https://support.google.com/analytics/answer/1205784), [goal completion
rate](https://support.google.com/analytics/answer/1012040), etc.) by device
memory to see if there are any correlations.

Since device memory is a custom dimension rather than a built-in dimension, you
won't see it in any of the standard reports. To access this data you'll have to
[create a custom report](https://support.google.com/analytics/answer/1151300).
For example, the configuration for a custom report that compares load times by
device memory might look like this:

And the report it generates might looks like this:

Once you're collecting device memory data and have a baseline for how users are
experiencing your application across all ranges of the memory spectrum, you can
experiment with serving different resources to different users (using the
techniques described in the section above). Afterwards, you'll be able to look at
the results and see if they've improved.

## Wrapping up

This post outlines how to use the Device Memory API to tailor your application
to the capabilities of your users' devices, and it shows how to measure how
these users experience your app.

While this post focuses on the Device Memory API, most of the techniques
described here could be applied to any API that reports device capabilities or
[network conditions](https://www.chromestatus.com/feature/6338383617982464).

As the device landscape continues to widen, it's more important than ever that
web developers consider the entire spectrum of users when making decisions that
affect their experience.

redpajama_set_name: RedPajamaGithub


Did The FBI Tap Clinton's Phones?
Consider how the New York Times covered a recent hearing on Capitol Hill: "…the Joint Chiefs of Staff said Tuesday that pet military projects sought by House Speaker Newt Gingrich and Senator Majority Leader Trent Lott, and Congress' refusal to close unnecessary bases, are weakening the nation's defense." Despite the implications of that lead paragraph in a front page article, the truth is that the Joint Chiefs never mentioned Gingrich or Lott by name. The Times had converted some real but largely insignificant testimony by the Joint Chiefs into a personal blast at the top Republicans in Congress. Why?
The apparent reason is that the Times reporter, Eric Schmitt, was determined to take the Clinton Administration off the hook for pursuing policies that have gutted our military. A week earlier, President Clinton himself admitted in a letter that the defense budget is being strained by "operational and maintenance shortfalls." Clinton said there is a clear need to increase purchases of new weapons and military equipment to replace aging aircraft, ships and ground vehicles.
After making that sweeping statement, the Times proceeded, just one day later, in running another editorial telling the Pentagon where it ought to spend the money. In an editorial about human rights problems in Kosvo in Yugoslavia, the Times strongly urged the use of the U.S. military to carry out bombing raids on this European country.
The contradiction should be obvious: Pentagon resources are being strained by a Clinton policy, supported by the New York Times, of committing our troops to various trouble spots around the world. This is one of the big reasons for our readiness problem. A Congressional expert on foreign policy issues who saw both editorials told us: "This is a textbook example of liberals trashing an adequate defense capability while demanding the armed forces undertake endless missions unrelated to national defense." Now that the debate over national defense has begun, it is important that newspapers like the New York Times give us the facts. The Times cannot have it both ways, and it should not distort testimony before a Congressional committee.


March 18, 2019 TCNJ at Southern Me.
Thomas Persichetti singled to center field; Danny Borup advanced to second.
Tommy McCarthy singled to center field; Thomas Persichetti advanced to second; Danny Borup advanced to third.
Jacob Simon doubled to left center, 3 RBI; Tommy McCarthy scored; Thomas Persichetti scored; Danny Borup scored.
Aydon Chavis singled to shortstop.
Danny Borup singled to shortstop; Aydon Chavis advanced to second.
Thomas Persichetti hit by pitch; Danny Borup advanced to second; Aydon Chavis advanced to third.
David Cardona III singled through the right side, 2 RBI; Thomas Persichetti advanced to third; Danny Borup scored; Aydon Chavis scored.
Gary Otten hit by pitch; Jacob Simon advanced to second.
Cody Braga to p for Joshua Joy.
Gary Otten advanced to third; Jacob Simon scored on a wild pitch.
Andrew Olszak walked; Zach Quintal advanced to second.
Jake Dexter singled through the left side, RBI; Andrew Olszak advanced to second; Zach Quintal scored.
Thomas Persichetti reached first on an error by 3b.
David Cardona III singled to center field; Thomas Persichetti advanced to third.
Tommy McCarthy grounded out to 2b, RBI; David Cardona III advanced to second; Thomas Persichetti scored, unearned.
Jacob Simon hit by pitch.
Andrew Hillier singled to right center.
David Cardona III singled to right field.
Dylan Hapworth doubled to right field; Jake Dexter advanced to third.
Devin Warren doubled to left center, 2 RBI; Dylan Hapworth scored; Jake Dexter scored.
Andrew Hillier singled, out at second lf to ss to 2b, RBI; Devin Warren scored.
Anthony Degifico pinch hit for Arlo Pike.
Jack Sylvia pinch hit for Sam Troiano.
Colton Lawrence to p for Cody Braga.
Jacob Simon advanced to second on a balk.
Jacob Simon advanced to third on a balk.
Gary Otten hit by pitch.
Matt Giacose singled up the middle, advanced to second, 2 RBI; Gary Otten scored; Jacob Simon scored.
Danny Borup singled to left field, RBI; Matt Giacose scored.
Dylan Crowley to p for Michael Walley.
Thomas Persichetti advanced to third on a wild pitch, scored on a throwing error by c.
Gary Otten doubled down the lf line.
Matt Volpe pinch hit for Ryan Fischer.
Matt Volpe singled to left field; Gary Otten advanced to third.
Avery Epstein pinch ran for Matt Volpe.
Aydon Chavis singled to shortstop, RBI; Avery Epstein advanced to second; Gary Otten scored.
Aydon Chavis advanced to second; Avery Epstein advanced to third on a wild pitch.
Tom Vesosky to cf for Anthony Degifico.
Aydon Chavis advanced to third; Avery Epstein scored on a wild pitch.
Chris Reeder pinch hit for David Cardona III.
Chris Reeder walked; Danny Borup advanced to second.
Chris Reeder advanced to second; Danny Borup advanced to third; Aydon Chavis scored on a wild pitch.
Grant Sible pinch hit for Jacob Simon.
Tommy McCarthy advanced to second; Chris Reeder advanced to third; Danny Borup scored on a wild pitch.
Tyler Parke pinch hit for Jack Sylvia.
Jason Komulainen pinch hit for Zach Quintal.


I recently read this terrific blog post by David Skok, an expert on SaaS businesses and a General Partner at Matrix Partners, an early-stage venture capital firm based in Boston. This post included a lot of terrific sales-related benchmarking metrics for SaaS businesses collected by David and The Bridge Group. David was kind enough to allow me to share his learnings with all of you. So, here it goes.
Sample Studied: The study interviewed 384 SaaS executives. 89% in North America, $20MM median revenues, $25K median contract value, 60 day median sales cycle.
Territories: Companies keep it simple as long as they can; 61% of companies under $5MM have no territories--which falls to 10% for companies over $250MM in sales. Companies under $50MM that do create territories, do so: 63% by geography, 23% by named accounts and 9% by industry vertical.
Outside Sales Reps: Outside salespeople are expensive, especially for lower ticket products where you can't make the lifetime value of revenues exceed the cost of acquisition. So, no surprise that only 9% of the sales pipeline of a company under $5MM was generated by outside salespeople (leaning on marketing or inside salespeople instead), which jumps to 38% of the pipeline for companies between $50-$100MM in revenues, where they can better afford the costs.
Specialized Roles: Every client can have up to three people covering them--a sales development rep that close the first sale, an account executive that manages the long term relationship and future sales and a customer success person that manages operational fulfillment. Only 22% of companies under $5MM have all three roles, which increases to 44% for companies between $20-$50MM. And, the higher the average order value, the higher odds you get multiple roles filled (8% fill all three roles with under $5K ticket, which jumps to 56% with $100K+ ticket given the higher complexity of the sale).
Location: 24% of companies under $5MM have sales reps in multiple locations, which jumps to 95% for companies over $500MM. Surprisingly, the cost of that person is largely the same as the home office team, regardless of which market they are operating from.
Tenure: The average tenure of a salesperson is 2.4 years with the company. But, that increases with the average order value of the product: only 8% of salespeople stay with the company over four years in companies under $5K ticket, but jump to 31% with over $100K ticket. That speaks to more complex sales and the need to retain those selling experts--and, the higher compensation those salespeople are making with no need to look elsewhere for a new job.
Turnover: The average employee turnover in the sales team was a whopping 30%, half of which from involuntary terminations and half of which from voluntary resignations. The old adage bears true: never stop recruiting. And, what a painful process for your sales managers, having to retrain a third of their sales team every year, and the negative impact that has on sales productivity.
Compensation: The average compensation was $126K, comprised of a $62K base salary and a $64K commission for on-target sales. Understanding there is a wide range here, based on average ticket of the product. But, compensation is steadily rising; the amount of salespeople making more than $120K has increased from 18% to 51% in the last five years.
Quotas: The average quota was $770K, or 5.3x their total compensation for on-target sales. But, quotas increase with average ticket, from $578K for $5K ticket to $1.3MM for $100K+ ticket. That assumes selling low ticket products is easy and you should close 115 transactions a year (10 a month) and selling high ticket products is hard, selling only 13 transactions a year (one a month). Quotas have been increasing about 8% over the last two years, faster than inflation, as companies are asking their salespeople to do more production.
Commission Plan: On average, 37% of companies offer a flat compensation plan (regardless of sales production), 24% offer a gradually increasing commission plan, 28% offer a sharply increasing commission plan (that accelerates with achievement over plan) and 11% offer a steeply increasing commission plan (often with a sales cliff before material commissions kick in). I am surprised a third of companies don't tie compensation to performance--please fix that!!
Demos: The number of demos is dependent on average ticket. Companies with an averge ticket under $5K do 11.3 demos a week (closing around 25% of them) and companies with a ticket over $100K do 3.6 demos a week (closing about 7% of them, on average). I am surprised the close rate was not higher than 10% in all cases, which I typically shoot for. That is the difference of 43% more sales!!
Tech Spend: Excluding the base CRM costs, the average salesperson spends around $477 on additional software to help them with their jobs. That typically gets you email automation, contact data appending, contract e-signatures and LinkedIn's Sales Navigator tools. The more sophisticated companies spend an additional $500 to get call recordings and conversion analytics tools. The below chart shows even more advanced technologies which are early in their adoption curve.
Titles: Titles materially vary by size of company--a VP in a small company may be the equivalent experience of a Director in a medium company or a Manager in a big company. The most senior person in a company under $20MM is typically a VP or CXO, 45% of the time. Where the most senior person in a company over $100MM, may have the Manager title, 71% of the time. So, be careful how your craft your job postings and ask smart questions during interviews to make sure you are not comparing apples with oranges. As a rule of thumb: Directors are great strategists/leaders, Managers are great coaches and Team Leaders are great role models in a hybrid contributor/manager role. Team leaders typically manage a team of 7.2 account executives, excluding themselves.
Struggles: I am guessing you are all in good company here. 49% of companies struggle with team productivity/performance; 30% with recruiting/hiring; 26% with onboarding/training and 19% with forecast accuracy. Numbers which have not materially improved over the years, despite all the advancements in technology. Driving sales is never easy.
Hopefully, you agree that are some great sales benchmarking metrics herein, which can help you in managing your own SaaS sales organizations. Thanks again, David, for allowing me to share some of your insights with our Red Rocket readers. Be sure to read the full blog post for more details and you can follow David on Twitter at: @bostonvc. Happy hunting!


text:
Auzoux ist der Familienname folgender Personen:
 Louis Auzoux (1797–1880), französischer Modelleur
 Yann Auzoux (* 1972), kamerunischer Tennisspieler

Siehe auch:
 Auzou

redpajama_set_name: RedPajamaWikipedia


I noticed a lot of television commentators wondering why no one predicted the unrest in Egypt. I'd just like to draw attention to the number 1 item in my New Year's list of 2011 challenges for US foreign policy. While it is not exactly a prediction of what we are seeing today on our television sets, it lays out the outlines of the challenge as we are now experiencing it and suggests that corporate media is just listening to the wrong inside-the-beltway pundits if they weren't hearing about these potentialities in the Egyptian scene before January 25.


text:
package com.terradue.dsi.model;

import static javax.xml.bind.annotation.XmlAccessType.FIELD;

import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * @since 0.2
 */
@XmlAccessorType( FIELD )
@XmlRootElement( name = "networkStorageCreationInfoMPO" )
public final class NetworkStorageCreation
{

    @XmlElement( name = "networkStorageName" )
    private String name;

    @XmlElement( name = "networkStorageDescription" )
    private String description;

    @XmlElement( name = "networkStorageProvider" )
    private String provider;

    @XmlElement( name = "networkStorageSizeGb" )
    private int size;

    @XmlElement( name = "networkStorageExternalProtocol" )
    private String externalProtocol;

    @XmlElement( name = "network" )
    private Network network;

    @XmlElement( name = "providerId" )
    private String providerId;

    @XmlElement( name = "qualifierId" )
    private String qualifierId;

    public String getName()
    {
        return name;
    }

    public void setName( String name )
    {
        this.name = name;
    }

    public String getDescription()
    {
        return description;
    }

    public void setDescription( String description )
    {
        this.description = description;
    }

    public String getProvider()
    {
        return provider;
    }

    public void setProvider( String provider )
    {
        this.provider = provider;
    }

    public int getSize()
    {
        return size;
    }

    public void setSize( int size )
    {
        this.size = size;
    }

    public String getExternalProtocol()
    {
        return externalProtocol;
    }

    public void setExternalProtocol( String externalProtocol )
    {
        this.externalProtocol = externalProtocol;
    }

    public Network getNetwork()
    {
        return network;
    }

    public void setNetwork( Network network )
    {
        this.network = network;
    }

    public String getProviderId()
    {
        return providerId;
    }

    public void setProviderId( String providerId )
    {
        this.providerId = providerId;
    }

    public String getQualifierId()
    {
        return qualifierId;
    }

    public void setQualifierId( String qualifierId )
    {
        this.qualifierId = qualifierId;
    }

    public static final class Builder
    {

        private final NetworkStorageCreation networkStorage = new NetworkStorageCreation();

        public Builder()
        {
            networkStorage.setNetwork( new Network() );
        }

        public Builder setDescription( String description )
        {
            networkStorage.setDescription( description );
            return this;
        }

        public Builder setExternalProtocol( String externalProtocol )
        {
            networkStorage.setExternalProtocol( externalProtocol );
            return this;
        }

        public Builder setName( String name )
        {
            networkStorage.setName( name );
            return this;
        }

        public Builder setProvider( String provider )
        {
            networkStorage.setProvider( provider );
            return this;
        }

        public Builder setProviderId( String providerId )
        {
            networkStorage.setProviderId( providerId );
            return this;
        }

        public Builder setQualifierId( String qualifierId )
        {
            networkStorage.setQualifierId( qualifierId );
            return this;
        }

        public Builder setSize( int size )
        {
            networkStorage.setSize( size );
            return this;
        }

        public Builder setNetworkId( String networkId )
        {
            networkStorage.getNetwork().setId( networkId );
            return this;
        }

        public NetworkStorageCreation build()
        {
            return networkStorage;
        }

    }

}


But It has the Recycling Symbol!
Just because it has the recycling symbol doesn't mean your closest recycling center is going to take it. First your material needs a market. And second, the symbol of those arrows chasing each other in a triangle do NOT mean an item can be recycled. It's just a resin identification code from the Society of Plastics to identify the polymer type of plastic that a material is. Here's a quick reference of what the symbols stand for, their recycle rate, examples of what is made from them and >>> what they can be recycled into / risks.
Linda Fritz is owner of Sun Sugar Farms and the creator of CRESBI® Crate Systems - a patented system of collapsable, stackable, reusable grocery crates combined with a made-in-America strap, thermal insulation, and carry totes.